Интерфейс против абстрактного класса (общий ОО)

1413

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

Исходя из своего опыта, я думаю, что это правда. Если я не понял, пожалуйста, дайте мне знать.

Интерфейс:

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

Абстрактный класс:

Только абстрактные методы должны быть реализованы подклассом. Класс Abstract может иметь нормальные методы с реализациями. Абстрактный класс также может иметь переменные класса, кроме событий, делегатов, свойств и методов. Класс может реализовать только один абстрактный класс только из-за отсутствия Multi-наследования в C #.

  1. После всего этого интервьюер задал вопрос: «Что если бы у вас был класс Abstract только с абстрактными методами? Чем бы он отличался от интерфейса?» Я не знал ответа, но я думаю, что это наследство, как упомянуто выше, верно?

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

Смотрите также :

Houman
источник
412
Хотя я думаю, что важно знать разницу между ними, это не очень хороший вопрос для интервью. Если только работа не была написанием книги по ОО темам. Тебе лучше не работать на этих динь летучих мышей.
Алан
107
@Alan: Мне на самом деле нравится это как вопрос для интервью, но я бы не стал так преследовать кого-то по этому поводу - я бы, вероятно, опубликовал это больше как «Где бы вы выбрали интерфейс вместо абстрактного базового класса при определении иерархии? или что-то подобное.
Рид Копси
11
Может быть, они хотели получить более сфокусированный ответ ... хотя, как и вы, я бы отнесся к этому как к техническому вопросу.
CurtainDog
16
Хорошие табличные различия здесь: mindprod.com/jgloss/interfacevsabstract.html
Rajat_R
30
@Kave: I insisted you can't have a public variable inside an interface.я думаю, что интерфейс может иметь открытую переменную. Фактически переменные в интерфейсе автоматически становятся открытыми и окончательными.
ученик

Ответы:

746

Хотя ваш вопрос указывает на то, что он относится к «общепринятым нормам», похоже, что он действительно фокусируется на использовании этих терминов в .NET.

В .NET (аналогично для Java):

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

Как общие термины ОО, различия не обязательно четко определены. Например, есть программисты на C ++, которые могут иметь похожие жесткие определения (интерфейсы являются строгим подмножеством абстрактных классов, которые не могут содержать реализацию), в то время как некоторые могут сказать, что абстрактный класс с некоторыми реализациями по умолчанию все еще является интерфейсом или что неабстрактный класс все еще может определять интерфейс.

В действительности, существует идиома C ++, называемая не-виртуальным интерфейсом (NVI), где открытые методы - это не виртуальные методы, которые «одобряются» для частных виртуальных методов:

Майкл Берр
источник
7
Спасибо. Я думаю, что поскольку в вашем ответе упоминается состояние + хороший обзор всего остального, я отмечаю ваш ответ как окончательный ответ. Вы правы, я попросил генерального OO, так как мой первый интервьюер попросил генерального OO, но так как я парень на C #, я склонен забывать об этом. ;-) Также спасибо за объяснение C ++, как всегда, C ++ просто сногсшибателен.
Хоуман
6
Я думаю, что ключевой момент в объяснении, которое предоставил Майкл, заключается в том, что при реализации интерфейса вы ДОЛЖНЫ реализовывать все члены в интерфейсе, но при наследовании от абстрактного класса дочернему классу НЕ ТРЕБУЕТСЯ реализовывать члены его родителя
Гильермо Гомес,
82
+1: я был бы готов поспорить, что эти обезьяны, проводящие интервью, даже не понимают, что другие языки реализуют ОО по-другому.
Гонки легкости на орбите
2
@JL Я не понимаю, в чем проблема. Вы, кажется, перепутали абстрактный метод с абстрактным классом. Абстрактные методы не имеют реализации. Однако, внутри абстрактного класса , некоторые методы могут быть абстрактными (т.е. без реализации) в то время как некоторые другие могут действительно иметь реализацию.
xji
19
Обратите внимание, что в Java 8 теперь вы можете иметь методы по умолчанию и статические методы в интерфейсах, что означает, что интерфейсы Java могут иметь реализацию. Ссылка здесь . Очевидно, вы ссылались в основном на .NET, так что это всего лишь наблюдение, относящееся к Java.
Давтом
867

Как насчет аналогии: когда я был в ВВС, я прошел подготовку пилотов и стал пилотом ВВС США (ВВС США). В тот момент я не был квалифицирован, чтобы летать на чем-либо, и должен был посещать обучение по типу самолета. После того, как я получил квалификацию, я был пилотом (абстрактный класс) и пилотом C-141 (конкретный класс). На одном из моих заданий мне дали дополнительную обязанность: офицер безопасности. Теперь я был еще пилотом и пилотом C-141, но я также выполнял обязанности сотрудника по безопасности (я, так сказать, реализовал ISafetyOfficer). Пилот не должен был быть офицером безопасности, другие люди тоже могли это сделать.

Все пилоты ВВС США должны следовать определенным правилам военно-воздушных сил, а все пилоты C-141 (или F-16, или T-38) являются «пилотами ВВС США». Любой может быть офицером безопасности. Итак, подведем итог:

  • Пилот: абстрактный класс
  • C-141 Pilot: класс бетона
  • Сотрудник по безопасности: интерфейс

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

сойка
источник
87
Мне очень нравится эта аналогия, она использует простой пример, чтобы объяснить немного сложную тему
Кевин Бауэрсокс
13
Это лучший способ понять сложную терминологию ОО. Короче говоря, вся теория имеет смысл только тогда, когда вы можете использовать ее практически. @ Джей, ты, например, действительно легко понять несколько пунктов пули (в основном пронизывающий разум вместо того, чтобы быть поглощенным!)
против
54
Я все еще немного смущен. Скажем, вы получили квалификации F-16 и T-38, поэтому теперь класс Jayне может наследоваться от нескольких классов (пилот C-141, пилот F-16 и пилот T-38), означает ли это, что чьи классы должны стать интерфейсами? Спасибо
Алексей Окрушко
37
Многие люди справедливо дали +1 к комментарию Алекса, поскольку он показывает некоторую слабость в этом примере. Во-первых, я бы сказал, что Джей будет экземпляром C-141Pilot, а не его собственным классом. Кроме того, поскольку в ВВС США 99% всех пилотов квалифицируются только на одном самолете за раз (FCF и испытательные пилоты являются заметными исключениями), я не рассматривал множественные квалификации и то, как это может быть реализовано. Как мне известно о пилоте, который 50 лет назад получил квалификацию в 25 различных самолетах одновременно, я думаю, что это иллюстрирует то, как мы НЕ хотим использовать множественное наследование.
Джей
20
Поскольку маловероятно, что один пилот будет летать одновременно более чем на одном самолете, это будет хорошей возможностью для реализации схемы стратегии. Пилот будет иметь коллекцию сертификатов и выбрать правильный во время выполнения. Сертификаты будут кодироваться как поведения, которые будут реализовывать интерфейс IFlyPlane с методами TakeOff, Land, Eject.
Майкл Блэкберн
221

Я думаю, что ответ, который они ищут, - это принципиальное различие или философское отличие OPPS.

Наследование абстрактного класса используется, когда производный класс разделяет основные свойства и поведение абстрактного класса. Тип поведения, который на самом деле определяет класс.

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

Например, Автомобиль и Грузовик имеют много основных свойств и поведения абстрактного класса Automobile, но они также имеют некоторое периферийное поведение, такое как Генерация выхлопных газов, которое разделяют даже не автомобильные классы, такие как Drillers или PowerGenerators, и не обязательно определяют Автомобиль или Грузовик. Таким образом, Car, Truck, Driller и PowerGenerator могут использовать один и тот же интерфейс IExhaust.

Prasun
источник
32
Я думаю, что еще лучшая аналогия была бы «использует топливо», которая показала бы контрактную природу интерфейса.
Pureferret
@Pureferret, если accelerateявляется частью основного поведения автомобильного абстрактного класса, то я не могу сказать, что accelerateпоказывает характер контракта . что такое контрактный характер? почему это слово contractвводится всякий раз, когда мы говорим interface?
переобмена
@overexchange, потому что обычно интерфейс - это место, где встречаются две «поверхности», но слово «контракт» подразумевает, что существует соглашение о том, как встречаются две «поверхности». Не имеет смысла (по крайней мере для меня), что генерация выхлопных газов - это то, с чем вы «соглашаетесь». Но имеет смысл (опять же для меня), что вы можете договориться о необходимости использования топлива.
Pureferret
1
@Pureferret Я поднял запрос по ссылке для того же
overexchange
1
@Pureferret Если interfaceнеобходимо иметь периферийное поведение, то почему public interface List<E> extends Collection<E> {}он предназначен для описания основного поведения list? это на самом деле противоречит ответу прасуна. Оба Collection<E>и List<E>здесь интерфейсы.
сверхобмена
198

Коротко: Абстрактные классы используются для моделирования иерархии классов похожих классов (например, Animal может быть абстрактным классом, а Human, Lion, Tiger могут быть конкретными производными классами)

А ТАКЖЕ

Интерфейс используется для связи между 2 подобными / не похожими классами, которые не заботятся о типе класса, реализующего интерфейс (например, Высота может быть свойством интерфейса и может быть реализована человеком, зданием, деревом. Неважно, можете ли вы есть , вы можете плавать, вы можете умереть или что-нибудь еще ... это имеет значение только то, что вам нужно иметь высоту (реализация в вашем классе)).

Дананай
источник
7
Мне очень нравится этот ответ, потому что иногда трудно ответить на вопрос «что» отличается между вещами, рассматривая нечто более абстрактное, такое как намерение , а не только структуру (поскольку структурно интерфейс и чистый абстрактный класс во многом совпадают) предмет).
LostSalad
Легко перечислить, что абстрактный класс против интерфейса может делать на определенном языке, но сложнее создать абстракцию, чтобы придать объекту смысл и ответственность, а то, что вы сказали, полностью возобновляет использование концепции 2 в ОО. Спасибо!
Самуил
2
@dhananjay: я вижу, как Высота может быть отделена от концепции класса Animal и может быть от другого другого класса, но что именно вы подразумеваете под "связью" между классами? Это просто определение высоты для своего класса, верно?
TTT
77

Есть несколько других отличий -

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

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

Абстрактные базовые классы могут быть изменены в v2 + без нарушения API. Изменения в интерфейсах разрушают изменения.

[C # /. NET Specific] Интерфейсы, в отличие от абстрактных базовых классов, могут применяться к типам значений (структурам). Структуры не могут наследоваться от абстрактных базовых классов. Это позволяет применять поведенческие контракты / рекомендации по использованию к типам значений.

Рид Копси
источник
6
+1 за ключевой момент, что в классе может быть реализовано более одного интерфейса.
cgp
Это единственное реальное преимущество интерфейсов перед абстрактными базовыми классами, IMO. В противном случае, я согласен с рекомендациями по проектированию .NET, которые теперь говорят «предпочесть абстрактные базовые классы интерфейсам»
Рид Копси,
Хотя было бы интересно, если бы вы добавили, что его интерфейсы можно применять к любому классу.
cgp
1
@altCognito: понял, что вроде как обрабатывается второй абзац. Это напомнило мне, однако, что интерфейсы работают с типами значений, поэтому я добавил это.
Рид Копси
Большое спасибо за это точное описание. Это действительно очень полезно. Я новенький здесь. Жаль, что вы не можете выбрать два ответа как «ответ». Меня смущает то, что вы используете абстрактный базовый класс. Все абстрактные классы должны быть базовым классом подкласса. Зачем называть «базовый» дополнительный?
Хоуман
68

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

public class Vehicle {
    private Driver driver;
    private Seat[] seatArray; //In java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections).
    //You can define as many properties as you want here ...
}

Теперь велосипед ...

public class Bicycle extends Vehicle {
    //You define properties which are unique to bicycles here ...
    private Pedal pedal;
}

И автомобиль ...

public class Car extends Vehicle {
    private Engine engine;
    private Door[] doors;
}

Это все о наследовании . Мы используем их для классификации объектов на более простые формы Base и их потомков, как мы видели выше.

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

Абстрактные классы являются неполными объектами. Чтобы понять это далее, давайте еще раз рассмотрим аналогию с автомобилем.
Транспортное средство можно вести. Правильно? Но разные транспортные средства управляются по-разному ... Например, вы не можете водить машину так же, как водите велосипед.
Итак, как представить функцию движения транспортного средства? Труднее проверить, что это за тип транспортного средства, и управлять им со своей функцией; вам придется менять класс водителя снова и снова при добавлении нового типа транспортного средства.
Здесь идет роль абстрактных классов и методов. Вы можете определить метод drive как абстрактный, чтобы сказать, что каждый наследующий потомок должен реализовать эту функцию.
Так что, если вы измените класс автомобиля ...

//......Code of Vehicle Class
abstract public void drive();
//.....Code continues

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

Интерфейсы Интерфейсы полностью неполные. У них нет никаких свойств. Они просто указывают на то, что наследующие дети способны что-то делать ...
Предположим, у вас есть разные типы мобильных телефонов. У каждого из них есть разные способы выполнять разные функции; Пример: позвонить человеку. Производитель телефона указывает, как это сделать. Здесь мобильные телефоны могут набирать номер, то есть он может набирать номер. Давайте представим это как интерфейс.

public interface Dialable {
    public void dial(Number n);
}

Здесь создатель Dialable определяет, как набрать номер. Вам просто нужно дать ему номер для набора.

// Makers define how exactly dialable work inside.

Dialable PHONE1 = new Dialable() {
    public void dial(Number n) {
        //Do the phone1's own way to dial a number
    }
}

Dialable PHONE2 = new Dialable() {
    public void dial(Number n) {
        //Do the phone2's own way to dial a number
    }
}


//Suppose there is a function written by someone else, which expects a Dialable
......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE1;
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

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

И что еще более важно , если когда-нибудь вы переключите Dialable с другим

......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

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

Разработчики обычно используют интерфейсы для обеспечения взаимодействия (взаимозаменяемости) между объектами, поскольку они имеют общую функцию (точно так же, как вы можете перейти на стационарный или мобильный телефон, если вам просто нужно набрать номер). Короче говоря, интерфейсы - это гораздо более простая версия абстрактных классов без каких-либо свойств.
Также обратите внимание, что вы можете реализовать (наследовать) столько интерфейсов, сколько захотите, но вы можете расширять (наследовать) только один родительский класс.

Больше информации Абстрактные классы и интерфейсы

fz_salam
источник
Это неправда, что «Интерфейсы не имеют никаких свойств».
Bigeyes
@Bigeyes, Java не разрешает свойства в интерфейсах. Я думал, что то же самое было и в других языках. Не могли бы вы объяснить подробнее?
fz_salam
Я имею в виду C # /. Net. Пожалуйста , смотрите пример
Bigeyes
@Bigeyes for C #, где интерфейсы могут иметь свойства, разве это не вызывает проблему множественного наследования? Что происходит, когда класс использует несколько интерфейсов, которые определили одно и то же свойство? Просто любопытно спасибо
стекPusher
@happycoder: re: "Здесь, используя интерфейсы вместо абстрактных классов, вам не нужно беспокоиться о его свойствах. Пример: есть ли у него сенсорный экран или клавиатура, стационарный или мобильный телефон. Вам просто нужно знать, является ли он набираемым; наследует ли он (или реализует) интерфейс Dialable. " - Можете ли вы показать это в примере кода, также не видел, как это будет унаследовано ...
TTT
45

Если вы считаете javaязык ООП для ответа на этот вопрос, выпуск Java 8 приводит к тому, что часть содержимого в ответах выше устарела. Теперь интерфейс Java может иметь методы по умолчанию с конкретной реализацией.

Oracle сайт предоставляет основные различия между interfaceи abstractклассом.

Рассмотрите возможность использования абстрактных классов, если:

  1. Вы хотите поделиться кодом между несколькими тесно связанными классами.
  2. Вы ожидаете, что классы, которые расширяют ваш абстрактный класс, имеют много общих методов или полей или требуют модификаторов доступа, отличных от public (например, protected и private).
  3. Вы хотите объявить нестатические или не финальные поля.

Рассмотрите возможность использования интерфейсов, если:

  1. Вы ожидаете, что несвязанные классы будут реализовывать ваш интерфейс. Например, многие несвязанные объекты могут реализовать Serializableинтерфейс.
  2. Вы хотите указать поведение определенного типа данных, но не беспокоитесь о том, кто реализует его поведение.
  3. Вы хотите воспользоваться множественным наследованием типа.

Проще говоря, я хотел бы использовать

интерфейс: для реализации контракта несколькими несвязанными объектами

абстрактный класс: для реализации одинакового или разного поведения среди нескольких связанных объектов

Взгляните на пример кода, чтобы ясно понять вещи: как мне объяснить разницу между интерфейсом и классом Abstract?

Равиндра Бабу
источник
33

Интервьюеры лают странное дерево. Для языков, таких как C # и Java, есть разница, но в других языках, таких как C ++, нет. Теория ОО не различает их, а только синтаксис языка.

Абстрактный класс - это класс с реализацией и интерфейсом (чисто виртуальные методы), которые будут наследоваться. Интерфейсы обычно не имеют никакой реализации, а только чисто виртуальные функции.

В C # или Java абстрактный класс без какой-либо реализации отличается от интерфейса только синтаксисом, используемым для его наследования, и тем фактом, что вы можете наследовать только от одного.

Стив Роу
источник
Мне задали тот же вопрос неделю назад, у меня нет опыта работы с Java, но я уже некоторое время работаю с C ++. Интервьюер не указывал языки перед тем, как задавать вопрос, поэтому я просто объяснил, что интерфейсы в этом случае - это абстрактные классы без состояния или реализации любого рода. Я согласен, что это тоже странный вопрос.
Дакабди
31

Реализуя интерфейсы, вы получаете композицию (отношения «есть») вместо наследования (отношения «есть»). Это важный принцип, который нужно помнить, когда дело доходит до таких вещей, как шаблоны проектирования, когда вам нужно использовать интерфейсы для достижения композиции поведения вместо наследования.

TheTXI
источник
17
Интерфейсы достигают, IMO, больше отношения "Acts-as-a". Инкапсуляция позволяет добиться композиции лучше, чем интерфейс.
Рид Копси
12
Я не думаю, что реализация интерфейсов была бы под композицией.
Паван Диттакави
Кроме того, интерфейс более вероятно использовать для описания «возможностей», таких как IDisposable. Раньше он разделял функциональность между классами, чтобы эти классы могли что-то делать. Еще пример IFlyable может быть реализован птицей и самолетом. Но Bird может происходить от Class Creature, где воздушные суда происходят от AirCraft.
Питер. Ван
26

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

  1. Когда мы должны использовать интерфейс?

    если вы не знаете о реализации, просто у нас есть спецификация требований, то мы идем с интерфейсом

  2. Когда мы должны использовать абстрактный класс?

    если вы знаете реализацию, но не полностью (частично реализацию), тогда мы идем с классом Abstract.

    Интерфейс

    каждый метод по умолчанию открытый интерфейс означает, что интерфейс на 100% чистый.

    Аннотация

    может иметь конкретный метод и абстрактный метод, то есть метод Бетон, который имеет реализацию в абстрактном классе. Абстрактный класс - это класс, который объявлен абстрактным - он может включать или не включать абстрактные методы.

    Интерфейс

    Мы не можем объявить интерфейс как частный, защищенный

    В. Почему мы не объявляем интерфейс закрытым и защищенным?

    Потому что по умолчанию метод интерфейса является публичным абстрактным, поэтому мы не объявляем интерфейс закрытым и защищенным.

    Метод интерфейса
    также мы не можем объявить интерфейс как частный, защищенный, окончательный, статический, синхронизированный, родной .....

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

    Аннотация

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

    Интерфейс

    Переменные объявляются в интерфейсе как открытый статический финал по умолчанию, поэтому мы также не объявляем переменную как частную защищенную.

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

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

    Аннотация

    Абстрактная переменная не нуждается в объявлении public static final.

Я надеюсь, что эта статья полезна.

JegsVala
источник
4
Я не согласен с этой точкой зрения: Abstract class must have at lease one abstract method.возможно иметь класс Abstract без метода Abstract, если вы его реализуете. СПРАВКА: An abstract class is a class that is declared abstract—it may or may not include abstract methods.СПРАВОЧНЫЙ ИСТОЧНИК: docs.oracle.com/javase/tutorial/java/IandI/abstract.html
Devner
Вы говорите о технических деталях и реализации, вы не отвечаете на вопрос с точки зрения общего ООП
Биллал Бегерадж
26

С концептуальной точки зрения, сохранение реализации, правил, преимуществ и достижения любой цели программирования с использованием кого-либо или обоих, может или не может иметь код / ​​данные / свойство, бла-бла, одиночное или множественное наследование, все в стороне

1- Абстрактный (или чистый абстрактный) класс предназначен для реализации иерархии. Если ваши бизнес-объекты выглядят несколько структурно схожими, представляя только родительско-дочерние (иерархические) отношения, тогда будут использоваться классы наследования / абстрактные. Если ваша бизнес-модель не имеет иерархии, тогда не следует использовать наследование (здесь я не говорю о логике программирования, например, некоторые шаблоны проектирования требуют наследования). Концептуально абстрактный класс - это метод реализации иерархии бизнес-модели в ООП, он не имеет ничего общего с интерфейсами, фактически сравнивать абстрактный класс с интерфейсом бессмысленно, поскольку оба концептуально совершенно разные вещи, в интервью его просят просто проверить концепции, потому что, похоже, оба обеспечивают несколько одинаковую функциональность, когда речь идет о реализации, и мы, программисты, обычно уделяем больше внимания кодированию. Помните также, что абстракция отличается от абстрактного класса.

2- Интерфейс - это контракт, полная бизнес-функциональность, представленная одним или несколькими наборами функций. Вот почему он реализован, а не наследуется. Бизнес-объект (часть иерархии или нет) может иметь любое количество полных бизнес-функций. Это не имеет ничего общего с абстрактными классами, означает наследование в целом. Например, человек может запустить, слон может выполнить, птица может выполнить и т.д., все эти объекты различной иерархии будут реализовывать интерфейс RUN или интерфейс EAT или SPEAK. Не входите в реализацию, поскольку вы можете реализовать ее как наличие абстрактных классов для каждого типа, реализующего эти интерфейсы. Объект любой иерархии может иметь функциональность (интерфейс), которая не имеет ничего общего с его иерархией.

Я считаю, что интерфейсы не были изобретены для достижения множественного наследования или для демонстрации открытого поведения, и аналогично, чистые абстрактные классы не должны отменять интерфейсы, но интерфейс - это функциональность, которую может выполнять объект (через функции этого интерфейса), а абстрактный класс представляет родительский элемент иерархии для создания дочерних элементов, имеющих базовую структуру (свойство + функциональность) родительского элемента

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

Я полагаю, что оба интервьюера ожидали однозначного различия между этими двумя, а когда вы потерпели неудачу, они пытались подтолкнуть вас к этому различию, внедрив ОДНОГО как ДРУГОЕ

Что если у вас есть класс Abstract только с абстрактными методами?

bjan
источник
Это в значительной степени суммирует ответ на этот вопрос довольно хорошо.
Пранавн
реализована функциональность против расширенной структуры, приятно!
harshvchawla
21

Для .Net,

Ваш ответ Второму интервьюеру - также ответ на первый ... Абстрактные классы могут иметь реализацию, И состояние, интерфейсы не могут ...

РЕДАКТИРОВАТЬ: С другой стороны, я бы даже не использовал фразу «подкласс» (или фразу «наследование») для описания классов, которые «определены для реализации» интерфейса. Для меня интерфейс - это определение контракта, которому должен соответствовать класс, если он был определен для «реализации» этого интерфейса. Он ничего не наследует ... Вы должны сами все добавить, явно.

Чарльз Бретана
источник
2
Да! Государственный! Вот что имел в виду второй интервьюер со своим странным способом сказать «публичная переменная» внутри интерфейса. Гоша! Абстрактные классы могут иметь состояние, интерфейсы - нет! И да, все остальные также согласны с различиями в способах наследования, о которых я забыл упомянуть, но выяснил это уже позже. :) Спасибо всем!
Хоуман
4
Больше, чем просто состояние ... Абстрактные классы могут иметь РЕАЛИЗАЦИЮ. то есть они могут иметь методы с кодом, который на самом деле выполняется и выполняет что-то, что наследуется и выполняется экземплярами базовых классов ... Не так с интерфейсами
Чарльз Бретана
Более того, в каком-то смысле абстрактные классы МОГУТ быть созданы, их просто нужно создавать, используя определение производного класса, а не напрямую. Но переменные состояния, определенные в абстрактном классе, создаются в объекте, созданном путем обновления экземпляра производного класса. Этот экземпляр является экземпляром абстрактного класса, а также является экземпляром производного класса - в конце концов, он является производным от него. Ничто из этого не относится к интерфейсу.
Чарльз Бретана
Когда вы создаете экземпляр класса, определенного для реализации интерфейса, он не является «экземпляром» этого интерфейса, все, что делает синтаксис, - это заставляет компилятор проверять код для класса и гарантировать, что каждое поведение (метод, свойство , event, eventHandler и т. д.), который определяется интерфейсом, был реализован в коде для класса.
Чарльз Бретана
20

Интерфейс : следует использовать, если вы хотите наложить правило на компоненты, которые могут или не могут быть связаны друг с другом

Плюсы:

  1. Позволяет множественное наследование
  2. Обеспечивает абстракцию, не раскрывая, какой именно тип объекта используется в контексте
  3. обеспечивает согласованность конкретной подписью контракта

Минусы:

  1. Необходимо выполнить все контракты, определенные
  2. Не может иметь переменных или делегатов
  3. Однажды определенный не может быть изменен без нарушения всех классов

Абстрактный класс : должен использоваться там, где вы хотите иметь базовое или стандартное поведение или реализацию для компонентов, связанных друг с другом

Плюсы:

  1. Быстрее, чем интерфейс
  2. Имеет гибкость в реализации (вы можете реализовать ее полностью или частично)
  3. Может быть легко изменено без нарушения производных классов

Минусы:

  1. Не может быть создан
  2. Не поддерживает множественное наследование
бура вебмастер
источник
Определите быстрее. Это важно? Что это вообще значит? код операции для вызова функции в абстрактном классе быстрее, чем код операции для вызова функции в интерфейсе?
denis631
@ denis631 абстрактный класс немного быстрее интерфейса из-за поиска и вызова в интерфейсе метода. Прочитайте этот coderanch.com/t/503450/java/abstract-class-faster-interface
веб-мастер bourax
17

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

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

абстрактный класс: используется только для разложения некоторого кода между классами с одинаковой ответственностью. Обратите внимание, что это является основной причиной, по которой множественное наследование является плохой вещью в ООП, поскольку класс не должен обрабатывать многие обязанности ( вместо этого используйте композицию ).

Таким образом, интерфейсы играют реальную архитектурную роль, в то время как абстрактные классы являются почти только частью реализации (если вы, конечно, используете их правильно).

Gnucki
источник
13
After all that, the interviewer came up with the question "What if you had an 
Abstract class with only abstract methods? How would that be different
from an interface?" 

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

An another interviewer asked me what if you had a Public variable inside
the interface, how would that be different than in Abstract Class?

Переменные в интерфейсах по умолчанию являются общедоступными static и final. Вопрос может быть сформулирован так, как если бы все переменные в абстрактном классе были публичными? Ну, они все еще могут быть не статичными и не финальными в отличие от переменных в интерфейсах.

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

Аникет Тхакур
источник
13
  1. Интерфейс:
    • Мы не реализуем (или не определяем) методы, мы делаем это в производных классах.
    • Мы не объявляем переменные-члены в интерфейсах.
    • Интерфейсы выражают отношения HAS-A. Это означает, что они являются маской объектов.
  2. Абстрактный класс:
    • Мы можем объявлять и определять методы в абстрактном классе.
    • Мы скрываем конструкторы этого. Это означает, что нет никакого объекта, созданного из этого непосредственно.
    • Абстрактный класс может содержать переменные-члены.
    • Производные классы наследуются от абстрактного класса, что означает, что объекты из производных классов не маскируются, а наследуются от абстрактного класса. Отношения в этом случае IS-A.

Это мое мнение.

nautilusvn
источник
12

Скопировано из CLR через C # Джеффри Рихтером ...

Я часто слышу вопрос: «Должен ли я проектировать базовый тип или интерфейс?» Ответ не всегда однозначен.

Вот несколько рекомендаций, которые могут вам помочь:

■■ Соотношение IS-A и CAN-DO Тип может наследовать только одну реализацию. Если производный тип не может требовать отношения IS-A с базовым типом, не используйте базовый тип; использовать интерфейс. Интерфейсы подразумевают связь CAN-DO. Если кажется, что функциональность CAN-DO относится к различным типам объектов, используйте интерфейс. Например, тип может преобразовывать свои экземпляры в другой тип (IConvertible), тип может сериализовать свой экземпляр (ISerializable) и т. Д. Обратите внимание, что типы значений должны быть получены из System.ValueType, и, следовательно, они не могут быть получены из произвольного базового класса. В этом случае вы должны использовать отношение CAN-DO и определить интерфейс.

■■ Простота использования. Как разработчик, вам, как правило, проще определить новый тип, производный от базового типа, чем реализовать все методы интерфейса. Базовый тип может обеспечивать большую функциональность, поэтому производный тип, вероятно, нуждается лишь в небольших изменениях своего поведения. Если вы предоставляете интерфейс, новый тип должен реализовывать все элементы.

■■ Последовательная реализация Независимо от того, насколько хорошо документирован контракт интерфейса, очень маловероятно, что каждый будет выполнять контракт на 100 процентов правильно. Фактически, COM страдает от этой самой проблемы, поэтому некоторые COM-объекты корректно работают только с Microsoft Word или Windows Internet Explorer. Предоставляя базовый тип с хорошей реализацией по умолчанию, вы начинаете с использования типа, который работает и хорошо протестирован; затем вы можете изменить детали, которые нуждаются в модификации.

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

Дипак Мишра
источник
1
@AbdullahShoaib - это может быть кто угодно, но не может сделать, здесь есть разница. это основная причина, нам нужен интерфейс. поведение can-do также будет частью abstract class.
сверхобмена
10

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

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

Заметьте, C # также допускает наследование интерфейса.

joelmdev
источник
1
Использование терминов « горизонтальный» и « вертикальный» позволило очень четко представить разницу.
Infinity
10

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

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

Абстрактный класс является неполной реализацией . Класс может реализовывать или не реализовывать интерфейс, а абстрактный класс не должен реализовывать его полностью. Абстрактный класс без какой-либо реализации бесполезен, но абсолютно легален.

По сути, любой класс, абстрактный или нет, - это то, чем он является , а интерфейс - как вы его используете . Например: Animalможет быть абстрактный класс, реализующий некоторые основные метаболические функции и задающий абстрактные методы для дыхания и передвижения, не давая реализации, потому что он не знает, должен ли он дышать через жабры или легкие, и летает ли он, плавает, гуляет или ползает. Mountс другой стороны, это может быть интерфейс, который указывает, что вы можете ездить на животном, не зная, какое это животное (или вообще это животное!).

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

MCV
источник
10

Поскольку вы, возможно, получили теоретические знания от экспертов, я не буду тратить много слов, чтобы повторить все это здесь, а позвольте мне объяснить на простом примере, где мы можем использовать / не можем использовать Interfaceи Abstract class.

Предположим, вы разрабатываете приложение, чтобы перечислить все функции автомобилей. В разных точках вам нужно общее наследование, так как некоторые свойства, такие как DigitalFuelMeter, кондиционер, регулировка сиденья и т. Д., Являются общими для всех автомобилей. Аналогично, нам нужно наследование только для некоторых классов, поскольку некоторые свойства, такие как тормозная система (ABS, EBD), применимы только для некоторых автомобилей.

Приведенный ниже класс выступает в качестве базового класса для всех автомобилей:

public class Cars
{
    public string DigitalFuelMeter()
    {
        return "I have DigitalFuelMeter";
    }

    public string AirCondition()
    {
        return "I have AC";
    }

    public string SeatAdjust()
    {
        return "I can Adjust seat";
    }
}

Представьте, что у нас есть отдельный класс для каждой машины.

public class Alto : Cars
{
    // Have all the features of Car class    
}

public class Verna : Cars
{
    // Have all the features of Car class + Car need to inherit ABS as the Braking technology feature which is not in Cars        
}

public class Cruze : Cars
{
    // Have all the features of Car class + Car need to inherit EBD as the Braking technology feature which is not in Cars        
}

Предположим, нам нужен метод наследования технологии торможения для автомобилей Verna и Cruze (неприменимо для Alto). Хотя оба используют технологию торможения, «технология» отличается. Итак, мы создаем абстрактный класс, в котором метод будет объявлен как Abstract, и он должен быть реализован в его дочерних классах.

public abstract class Brake
{
    public abstract string GetBrakeTechnology();
}

Сейчас мы пытаемся унаследовать от этого абстрактного класса, и тип системы торможения реализован в Verna и Cruze:

public class Verna : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }       
}

public class Cruze : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
       return "I use EBD system for braking";
    }         
}

Видите проблему в двух вышеупомянутых классах? Они наследуются от нескольких классов, которые C # .Net не позволяет, хотя метод реализован в дочерних элементах. Здесь приходит необходимость интерфейса.

interface IBrakeTechnology
{
    string GetBrakeTechnology();
}

И реализация приведена ниже:

public class Verna : Cars, IBrakeTechnology
{
    public string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }
}

public class Cruze : Cars, IBrakeTechnology
{
   public string GetBrakeTechnology()
   {
       return "I use EBD system for braking";
   }        
}

Теперь Verna и Cruze могут добиться множественного наследования с помощью собственных технологий торможения с помощью интерфейса.

Сарат Аванаву
источник
4
Это одно из лучших объяснений из-за примеров.
Адам Мендоса
2
Это имеет смысл для меня, не ломая голову. Я просто пытался придумать пример автомобиля для моих учеников. Спасибо, что нашли время, чтобы собрать это вместе.
tazboy
9

Интерфейсы - это легкий способ реализации определенного поведения. Это один из способов думать.

fastcodejava
источник
8

Эти ответы слишком длинные.

  • Интерфейсы предназначены для определения поведения.

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

Это также объясняет, почему Java поддерживает единственное наследование классов, но не ограничивает интерфейсы. Потому что конкретный объект не может быть разными вещами, но может иметь разное поведение.

K.Miao
источник
7

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

2) Вы можете определить свойство в интерфейсе, поэтому класс, реализующий этот интерфейс, должен иметь это свойство.

Например:

  public interface IVariable
  {
      string name {get; set;}
  }

Класс, реализующий этот интерфейс, должен иметь такое свойство.

MRFerocius
источник
7

Хотя этот вопрос довольно старый, я хотел бы добавить еще один момент в пользу интерфейсов:

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

py2020
источник
1
Я полагаю, вы имеете в виду, что инструмент DI может внедрить класс, который реализует интерфейс. Некоторые такие инструменты могут также вводить классы, полученные из абстрактного класса, или вы говорите, что это невозможно?
Джон Сондерс
6

Из другого моего ответа , в основном касающегося того, когда использовать один против другого:

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

Адам Александр
источник
6

Типы интерфейса и абстрактные базовые классы

Адаптировано из Pro C # 5.0 и книги .NET 4.5 Framework .

Тип интерфейса может показаться очень похожим на абстрактный базовый класс. Напомним, что когда класс помечен как абстрактный, он может определять любое количество абстрактных членов, чтобы обеспечить полиморфный интерфейс для всех производных типов. Однако даже когда класс определяет набор абстрактных членов, он также может свободно определять любое количество конструкторов, полевых данных, неабстрактных членов (с реализацией) и так далее. Интерфейсы, с другой стороны, содержат только абстрактные определения членов. Полиморфный интерфейс, созданный абстрактным родительским классом, страдает одним серьезным ограничением в том, что только производные типы поддерживают члены, определенные абстрактным родительским классом. Однако в более крупных программных системах очень часто разрабатываются множественные иерархии классов, у которых нет общего родителя, кроме System.Object. Учитывая, что абстрактные члены в абстрактном базовом классе применяются только к производным типам, у нас нет способа настроить типы в разных иерархиях для поддержки одного и того же полиморфного интерфейса. В качестве примера предположим, что вы определили следующий абстрактный класс:

public abstract class CloneableType
{
// Only derived types can support this
// "polymorphic interface." Classes in other
// hierarchies have no access to this abstract
// member.
   public abstract object Clone();
}

Учитывая это определение, только члены, расширяющие CloneableType, могут поддерживать метод Clone (). Если вы создадите новый набор классов, которые не расширяют этот базовый класс, вы не сможете получить этот полиморфный интерфейс. Также вы можете вспомнить, что C # не поддерживает множественное наследование классов. Поэтому, если вы хотите создать MiniVan, который является автомобилем и является CloneableType, вы не можете сделать это:

// Nope! Multiple inheritance is not possible in C#
// for classes.
public class MiniVan : Car, CloneableType
{
}

Как вы могли догадаться, на помощь приходят типы интерфейсов. После того, как интерфейс был определен, он может быть реализован любым классом или структурой, в любой иерархии, в любом пространстве имен или любой сборке (написанной на любом языке программирования .NET). Как видите, интерфейсы очень полиморфны. Рассмотрим стандартный интерфейс .NET с именем ICloneable, определенный в пространстве имен System. Этот интерфейс определяет один метод с именем Clone ():

public interface ICloneable
{
object Clone();
}
Саид Роохулла Аллем
источник
6

Ответ на второй вопрос: publicпеременная, определенная в interface, static finalпо умолчанию, тогда как publicпеременная в abstractклассе является переменной экземпляра.

Равиндра Бабу
источник
6

Конечно, важно понимать поведение интерфейса и абстрактного класса в ООП (и как языки обрабатывают их), но я думаю, что также важно понимать, что именно означает каждый термин. Можете ли вы представить, что ifкоманда не работает точно как значение термина? Кроме того, на самом деле некоторые языки сокращают, даже больше, различия между интерфейсом и абстрактным ... если случайно однажды два термина работают почти одинаково, по крайней мере, вы можете сами определить, где (и почему) должен быть любой из них. используется для.

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

Интерфейс:

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

Аннотация:

Нечто, которое концентрирует в себе основные качества чего-то более обширного или более общего или нескольких вещей; сущность.

Пример:

Вы купили машину, и ей нужно топливо.

введите описание изображения здесь

Модель вашего автомобиля - XYZжанровая ABC, то есть это конкретный автомобиль, конкретный экземпляр автомобиля. Автомобиль не настоящий объект. Фактически это абстрактный набор стандартов (качеств) для создания конкретного объекта. Короче говоря, Car - это абстрактный класс , это «то, что концентрирует в себе основные качества чего-то более обширного или более общего» .

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

В объектно-ориентированном представлении топливо для жанра ABCне должно быть объявлено как класс, потому что нет никакого конкретного топлива для определенного жанра автомобиля. Несмотря на то, что ваш автомобиль может принимать абстрактный класс «Fuel» или «AutularFuel», вы должны помнить, что только некоторые из существующих автомобильных топлив соответствуют техническим требованиям, которые соответствуют требованиям, изложенным в руководстве по эксплуатации вашего автомобиля. Короче говоря, они должны реализовать интерфейс ABCGenreFuel , который «... позволяет отдельным и иногда несовместимым элементам эффективно координировать» .

добавление

Кроме того, я думаю, вы должны иметь в виду значение термина «класс», который (с того же сайта, о котором упоминалось ранее):

Учебный класс:

Количество людей или вещей, рассматриваемых как формирующие группу по причине общих признаков, характеристик, качеств или черт характера; вид;

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

Фелипп Оливейра
источник
1
слишком много пуха, не делайте это звучит более запутанно для людей, чем это может быть.
ganjeii
5

С точки зрения кодирования

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

С точки зрения дизайна

Сохраняйте его как абстрактный класс, если это отношение «является», и вам нужен поднабор или все функции. Сохраняйте его как интерфейс, если это отношения «следует делать».

Решите, что вам нужно: только применение политики или повторное использование кода и политика.

Вивек Вермани
источник
3

Пара других отличий:

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

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

Орлин Петров
источник
в Java интерфейс может иметь переменную-член, но по умолчанию они становятся открытыми статическими., так что интерфейс может иметь статические поля
Jitendra Vispute
Да, интерфейс может иметь статические поля. НО интерфейс не может иметь статических методов.
ученик