Наследование и интерфейсы - PullRequest
2 голосов
/ 06 ноября 2008

Это несколько дополнительный вопрос к этому вопросу .

Предположим, у меня есть дерево наследования следующим образом:

Car -> Ford -> Mustang -> MustangGT

Есть ли преимущество в определении интерфейсов для каждого этих классов? Пример:

ICar -> IFord -> IMustang -> IMustangGT

Я вижу, что, возможно, другие классы (например, Chevy) захотят реализовать Icar или IFord и, возможно, даже IMustang, но, вероятно, не IMustangGT, потому что это так специфично. Являются ли интерфейсы лишними в этом случае?

Кроме того, я думаю, что любой класс, который захочет реализовать IFord, определенно захочет использовать свое единственное наследование, наследуя от Ford, чтобы не дублировать код. Если это само собой разумеющееся, какая выгода от реализации IFord?

Ответы [ 14 ]

0 голосов
/ 06 ноября 2008

В этом ответе о разнице между интерфейсом и классом я объяснил, что:

  • показывает, что понятие является (в терминах «что является » действительным, во время компиляции) и используется для значений (MyInterface x = ...)
  • показывает, что концепт делает (фактически выполняется во время выполнения) и используется для значений или для объектов (MyClass x или aMyClass.method ())

Так что, если вам нужно сохранить в переменной «Ford» (понятие «значение») различные подклассы Ford, создайте IFord. В противном случае, не беспокойтесь, пока он вам действительно не понадобится.

Это один из критериев: если оно не выполнено, IFord, вероятно, бесполезен.
Если оно выполнено, то применяются другие критерии, раскрытые в предыдущих ответах: если у Ford более богатый API, чем у Car, IFord полезен для целей полиморфизма. Если нет, то ICar достаточно.

0 голосов
/ 06 ноября 2008

Тщательно продумайте, как ваши объекты должны взаимодействовать друг с другом в вашей проблемной области, и подумайте, нужно ли вам иметь более одной реализации конкретной абстрактной концепции. Используйте интерфейсы, чтобы обеспечить контракт вокруг концепции, с которой взаимодействуют другие объекты.

В вашем примере я бы предположил, что Ford, вероятно, является производителем, а Mustang - это значение ModelName, используемое производителем Ford, поэтому у вас может быть что-то похожее на:

IVehichle -> CarImpl, MotorbikeImpl - имеет-a Производитель имеет-много ModelNames

0 голосов
/ 06 ноября 2008

Наследовать только от интерфейсов и абстрактных классов.

Если у вас есть пара классов, которые почти одинаковы, и вам нужно реализовать большинство методов, используйте и интерфейс в сочетании с покупкой другого объекта.
Если классы Mustang такие разные, то не только создайте интерфейс ICar, но и IMustang.
Таким образом, класс Ford и Mustang могут наследовать от ICar, а Mustang и MustangGT - от ICar и IMustang.

Если вы реализуете класс Ford и метод такой же, как у Mustang, купите у Mustang:

class Ford{
  public function Foo(){
    ...
    Mustang mustang  = new Mustang();
    return mustang.Foo();
}
0 голосов
/ 06 ноября 2008

Я создам первые два уровня, ICar и IFord и оставляю второй уровень в покое, пока мне не понадобится интерфейс на этом втором уровне.

...