Я не спрашиваю о различиях между этими двумя, но почему интерфейсы чаще предпочитаются вместо абстрактных классов.
Почему предпочтительнее использовать интерфейсы вместо абстрактных классов?
Ответ 1
Самый очевидный "недостаток" абстрактных классов состоит в том, что наследующие типы могут наследоваться только от одного абстрактного класса.
Когда речь идет о интерфейсах, вы можете реализовать несколько интерфейсов.
Итак, когда вы разрабатываете свои типы, поэтому им нужно реализовать несколько контрактов, интерфейсы - это просто единственный вариант.
Итак, по крайней мере в мире С#, это, в сочетании с принципами SOLID, может объяснить склонность к интерфейсам.
Ответ 2
Я собираюсь сыграть здесь Адвокат дьявола...
Преимущество ABC состоит в том, что вы можете добавлять методы в ABC, не разбирая все производные классы. Если вы добавите метод в интерфейс, вы разбиваете каждый класс, реализующий этот интерфейс.
Совет по Microsoft поддерживает классы по интерфейсам по этой причине.
Кроме того, ABC может обеспечить реализацию по умолчанию для своих методов, когда это необходимо.
Кроме того, ABC может определять типы (такие как перечисления) и readonly 'константы', в то время как интерфейс не может.
Ответ 3
Это действительно очень загруженный вопрос. Они оба имеют свое применение в разных ситуациях.
Абстрактные классы
Класс Abstract используется, когда между подклассами есть общие функциональные возможности, но сам суперкласс никогда не будет существовать. Например, класс Person
никогда не будет существовать. Однако класс Woman
будет. Вместо того, чтобы повторять все методы, которые есть в Woman
, в Man
, Boy
и Girl
, мы просто возводим его в суперкласс, чтобы они все имели доступ к этой функциональности и могли переопределить методы, которые они хочу выполнять по-другому.
Интерфейсы
Интерфейсы используются, когда есть требование. То, как я на них смотрю, похоже на контракт. Соглашение заключается в том, что любой класс, реализующий Интерфейс, должен будет предоставить код для определенного количества методов.
Например, класс A Rock
и класс Ball
могут быть выброшены. Вместо метода броска мяча, который должен учитывать каждый объект, который может быть брошен, если каждый объект реализует интерфейс ThrowingItem
(я не хотел использовать слово Throwable
по понятным причинам), тогда метод может просто принять объект типа ThrowingItem
и точно знает, что согласованные методы будут там.
Это обеспечивает слабую связь между методом throw
и классами, которые его используют, поскольку все взаимодействие осуществляется через интерфейс.
Как видите, два разных типа используются в совершенно разных ситуациях, и сравнивать их - все равно что сравнивать яблоки и апельсины.
Изменение: у меня было некоторое время, чтобы подумать в последние несколько лет о азбуке.
За последние несколько лет не было ни одного случая, когда мне нужно было использовать наследование в моем производственном коде. Наследование становится трудным для тестирования в случае абстрактных классов. Как вы тестируете абстрактный класс? Вы не можете создать его экземпляр и создать экземпляр подкласса, если эти методы были переопределены полиморфным способом.
Вместо этого я провел все свое время, занимаясь сочинением. Это привело к появлению небольших служб с единственной ответственностью, которые очень легко проверить. Так что, как правило, композиция над наследованием.
Ответ 4
Как правило, мы используем интерфейсы, когда нам нечего сказать о реализации и абстрактных классах, когда у нас есть хотя бы частичная реализация.
Ответ 5
Вот мое эмпирическое правило, с которым я нашел больше всего, чтобы согласиться с:
- Начните с конкретного класса. Нет необходимости ничего абстрагировать, если он никогда не понадобится.
- Перейдите к абстракции, если найдете нужную
Как только вы перейдете к абстракции, вы можете решить, какой тип с помощью этой заметки: вы не можете наследовать от нескольких абстрактных классов, так что вы должны действительно решить между абстрактным классом или интерфейсом IMO, если вам нужна реализация или нет (если нет, то просто используйте интерфейс, чтобы впоследствии избежать столкновения с множественным наследованием)
Ответ 6
Если у вас есть тип, который может быть спроектирован как интерфейс или абстрактный класс, почему вы выбираете абстрактный класс?
В этом смысле мы используем только абстрактный класс, когда некоторые функции не могут быть выполнены в интерфейсе:
-
состояние. хотя интерфейс может запрашивать подклассы для реализации состояния, было бы удобнее использовать абстрактный суперкласс для хранения состояния.
-
ограничение доступа членов к
protected
. а все элементы интерфейса -public
-
статические методы. (обратите внимание, что в Java 8, возможно, интерфейс может иметь статические методы)
-
конкретные методы с реализациями. (обратите внимание, что в Java 8 методы интерфейса могут иметь defualt impl)
-
добавить более конкретные методы, не разбирая подклассы. (обратите внимание, что в Java 8 мы можем добавить дополнительные методы к существующему интерфейсу, если методы имеют значения по умолчанию)