Почему интерфейсы предпочтительнее абстрактных классов? - PullRequest
35 голосов
/ 12 марта 2009

Я недавно посетил интервью, и они задали мне вопрос «Почему интерфейсы предпочтительнее абстрактных классов?»

Я попытался дать несколько ответов, таких как:

  • Мы можем получить только одну Расширяемую функциональность
  • они на 100% абстрактные
  • Реализация не жестко закодирована

Они попросили меня взять любой из API JDBC, который вы используете. «Почему они интерфейсы?».

Могу ли я получить лучший ответ на этот вопрос?

Ответы [ 23 ]

55 голосов
/ 12 марта 2009

Этот вопрос интервью отражает определенное убеждение человека, задавшего вопрос. Я считаю, что человек не прав, и поэтому вы можете пойти одним из двух направлений.

  1. Дайте им ответ, который они хотят.
  2. С уважением не согласен.

Ответ, который они хотят, ну, другие постеры выдвинули на первый план те невероятно хорошо. Множественное наследование интерфейса, наследование заставляет класс делать выбор реализации, интерфейсы могут быть изменены проще.

Однако, если вы привели убедительные (и правильные) аргументы в своем несогласии, тогда интервьюер может принять к сведению. Во-первых, выделите положительные стороны интерфейсов, это ОБЯЗАТЕЛЬНО. Во-вторых, я бы сказал, что интерфейсы лучше во многих сценариях, но они также приводят к дублированию кода, что негативно. Если у вас есть широкий спектр подклассов, которые будут выполнять в основном ту же реализацию, плюс дополнительные функциональные возможности, тогда вам может понадобиться абстрактный класс. Он позволяет вам иметь много похожих объектов с мелкозернистой детализацией, в то время как только с интерфейсами у вас должно быть много разных объектов с почти дублированным кодом.

Интерфейсы имеют множество применений, и есть веская причина полагать, что они «лучше». Однако вы всегда должны использовать правильный инструмент для работы, а это значит, что вы не можете списывать абстрактные классы.

24 голосов
/ 12 марта 2009

В общем, и это ни в коем случае не является «правилом», которому следует слепо следовать, наиболее гибким является:

interface
   abstract class
       concrete class 1       
       concrete class 2

Интерфейс существует по нескольким причинам:

  • существующий класс, который уже что-то расширяет, может реализовать интерфейс (при условии, что у вас есть контроль над кодом для существующего класса)
  • существующий класс может быть подклассами, а подкласс может реализовывать интерфейс (при условии, что существующий класс является подклассом)

Это означает, что вы можете взять уже существующие классы (или просто классы, которые ДОЛЖНЫ расширяться из чего-то еще) и заставить их работать с вашим кодом.

Абстрактный класс предназначен для предоставления всех общих битов для конкретных классов. Абстрактный класс расширяется с того момента, когда вы пишете новые классы или модифицируете классы, которые хотите расширить, (если они расширяются из java.lang.Object).

Вы должны всегда (если у вас нет веских причин не делать этого) объявлять переменные (экземпляр, класс, локальные параметры и параметры метода) в качестве интерфейса.

23 голосов
/ 12 марта 2009

Вы получаете только один шанс на наследство. Если вы создаете абстрактный класс, а не интерфейс, тот, кто наследует ваш класс, также не может наследовать другой абстрактный класс.

10 голосов
/ 12 марта 2009

Вы можете реализовать более одного интерфейса, но вы можете наследовать только от одного класса

10 голосов
/ 12 марта 2009

Абстрактные классы

1.Не может быть создан независимо от их производных классов. Конструкторы абстрактных классов вызываются только их производными классами.

2. Определите сигнатуры абстрактных членов, которые должны реализовывать базовые классы.

3.Более расширяемы, чем интерфейсы, без нарушения совместимости версий. С абстрактными классами можно добавить дополнительные неабстрактные члены, которые могут наследовать все производные классы.

4.Может включать данные, хранящиеся в полях.

5. Разрешить для (виртуальных) членов, которые имеют реализацию, и, следовательно, предоставляют реализацию по умолчанию члена производного класса.

6. При получении из абстрактного класса используется единственный и единственный вариант базового класса подкласса.

Интерфейс

1.Не может быть создан экземпляр.

2.Внедрение всех членов интерфейса происходит в базовом классе. Невозможно реализовать только некоторые члены внутри реализующего класса.

3. Расширение интерфейсов дополнительными членами нарушает совместимость версий.

4.Не могу хранить данные. Поля могут быть указаны только на производных классах. Обходной путь для этого должен определить свойства, но без реализации.

5.Все члены автоматически становятся виртуальными и не могут включать никакую реализацию.

6. Хотя реализация по умолчанию не может появиться, классы, реализующие интерфейсы, могут продолжать наследоваться друг от друга.

7 голосов
/ 12 марта 2009

Как отмечают devinb и другие, похоже, что интервьюер демонстрирует свое невежество в том, что он не принимает ваши действительные ответы.

Однако упоминание JDBC может быть подсказкой. В этом случае, возможно, они просят о преимуществах клиента , кодирующего интерфейс вместо класса.

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

5 голосов
/ 12 марта 2009

Абстрактные классы имеют ряд потенциальных ловушек. Например, если вы переопределите метод, метод super() не будет вызван, если вы не вызовете его явно. Это может вызвать проблемы для плохо реализованных переопределяющих классов. Кроме того, существуют потенциальные проблемы с equals() при использовании наследования.

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

Определение интерфейса - это очень безопасный способ определить, как объект должен действовать, не рискуя хрупкостью, которую может дополнить другим классом, абстрактным или нет.

Кроме того, как вы упоминаете, вы можете расширять только один класс за раз, но вы можете реализовать столько интерфейсов, сколько пожелаете.

4 голосов
/ 15 марта 2009

Абстрактные классы используются, когда вы наследуете реализацию , интерфейсы используются, когда вы наследуете спецификацию . Стандарты JDBC гласят, что «Соединение должно делать это ». Это спецификация.

3 голосов
/ 12 марта 2009

"Почему интерфейсы предпочтительнее Абстрактные занятия? "

Другие посты проделали большую работу по изучению различий между интерфейсами и абстрактными классами, поэтому я не буду дублировать эти мысли.

Но, глядя на вопрос об интервью, лучше спросить: " Когда предпочтительнее ли интерфейсы перед абстрактными классами?" (и наоборот).

Как и в большинстве программных конструкций, они доступны по причине, и абсолютные утверждения, подобные приведенному в вопросе об интервью, имеют тенденцию пропускать это. Это напоминает мне все утверждения, которые вы когда-либо читали относительно оператора goto в C. «Вы никогда не должны использовать goto - это показывает плохие навыки программирования» Тем не менее, goto всегда имел соответствующее применение.

3 голосов
/ 12 марта 2009

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

У вас также есть только одно наследство, поэтому вам следует убедиться, что вы используете его по надлежащим причинам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...