Интерфейс против абстрактного класса (общий OO)
Недавно у меня было два телефонных интервью, в которых меня спрашивали о различиях между интерфейсом и абстрактным классом. Я объяснил все аспекты, о которых я мог думать, но, похоже, они ждут, когда я расскажу что-то конкретное, и я не знаю, что это такое.
По моему опыту, я считаю следующее. Если у меня отсутствует основная точка, пожалуйста, дайте мне знать.
Интерфейс:
Каждый отдельный метод, объявленный в интерфейсе, должен быть реализован в подклассе.
В интерфейсе могут существовать только события, делегаты, свойства (С#) и методы. Класс может реализовывать несколько интерфейсов.
Абстрактный класс:
Подкласс должен выполнять только абстрактные методы. Класс Abstract может иметь нормальные методы с реализациями. Абстрактный класс также может иметь переменные класса рядом с событиями, делегатами, свойствами и методами. Класс может реализовать только один абстрактный класс только из-за отсутствия множественного наследования в С#.
-
После этого интервьюер придумал вопрос "Что, если бы у вас был абстрактный класс с абстрактными методами? Как это будет отличаться от интерфейса?" Я не знал ответа, но я думаю, что это наследование, как указано выше, правильно?
-
Другой интервьюер спросил меня, что, если у вас была переменная Public внутри интерфейса, как бы это отличалось от абстрактного класса? Я настаивал, что вы не можете иметь переменную public внутри интерфейса. Я не знал, что он хотел услышать, но он тоже не был удовлетворен.
См. также:
Ответы
Ответ 1
Пока ваш вопрос указывает на "общий OO", на самом деле это, похоже, фокусируется на использовании этих терминов .NET.
В .NET(аналогично Java):
- интерфейсы могут не иметь состояния или реализации
- класс, реализующий интерфейс, должен обеспечить реализацию всех методов этого интерфейса
- абстрактные классы могут содержать состояние (элементы данных) и/или реализацию (методы)
- абстрактные классы могут быть наследованы без реализации абстрактных методов (хотя такой производный класс является абстрактным)
- интерфейсы могут быть многонаследованными, абстрактные классы могут не быть (это, вероятно, ключевая конкретная причина, по которой интерфейсы существуют отдельно от abtract классов - они позволяют реализовать множественное наследование, которое устраняет многие проблемы общего MI).
Как общие члены OO, различия не обязательно четко определены. Например, есть программисты на C++, которые могут придерживаться подобных жестких определений (интерфейсы представляют собой строгий подмножество абстрактных классов, которые не могут содержать реализацию), в то время как некоторые могут сказать, что абстрактный класс с некоторыми реализациями по умолчанию все еще является интерфейсом или что не абстрактный класс все еще может определить интерфейс.
В самом деле, есть идиома С++, называемая не виртуальным интерфейсом (NVI), где общедоступные методы - это не виртуальные методы, которые "thunk" для частных виртуальных методов:
Ответ 2
Как насчет аналогий: когда я был в ВВС, я пошел на пилотную подготовку и стал пилотом ВВС США (ВВС США). В тот момент я не был способен летать ни на что, и должен был учиться на самолете. Как только я получил квалификацию, я был пилотом (класс Abstract) и пилотом C-141 (конкретный класс). По одному из моих заданий мне была предоставлена дополнительная пошлина: сотрудник службы безопасности. Теперь я все еще пилот и пилот C-141, но я также выполнял обязанности сотрудника по вопросам безопасности (я, так сказать, реализовал ISafetyOfficer). Пилот не должен был быть офицером безопасности, другие люди тоже могли бы это сделать.
Все пилоты ВВС США должны соблюдать некоторые правила ВВС, и все пилоты C-141 (или F-16 или T-38) являются "пилотами ВВС США". Любой может быть офицером безопасности. Итак, подведем итог:
- Пилот: абстрактный класс
- C-141 Pilot: конкретный класс
- Сотрудник ISafety: интерфейс
добавлено примечание: это должно было быть аналогией, чтобы помочь объяснить концепцию, а не рекомендацию по кодированию. См. Различные комментарии ниже, обсуждение интересно.
Ответ 3
Я думаю, что ответ, который они ищут, является фундаментальной или OPPS-философской разницей.
Наследование абстрактного класса используется, когда производный класс разделяет основные свойства и поведение абстрактного класса. Тип поведения, который фактически определяет класс.
С другой стороны, наследование интерфейса используется, когда классы совместно используют периферийное поведение, которые не обязательно определяют производный класс.
Например, Автомобиль и грузовик разделяют множество основных свойств и поведения автомобильного абстрактного класса, но они также разделяют некоторое периферийное поведение, такое как генерация выхлопа, который разделяют даже не автомобильные классы, такие как Drillers или PowerGenerators, и не обязательно определяет автомобиль или грузовик, поэтому Car, Truck, Driller и PowerGenerator могут использовать один и тот же интерфейс IExhaust.
Ответ 4
Short: абстрактные классы используются для Моделирования иерархии классов похожих классов (например, Animal может быть абстрактным классом, а Human, Lion, Tiger могут быть конкретными производными классами)
И
Интерфейс используется для Коммуникации между двумя аналогичными/не похожими классами, которые не заботятся о типе реализующего интерфейс интерфейса (например, Height может быть интерфейсом, и он может быть реализован Human, Building, Дерево. Не имеет значения, можете ли вы поесть, вы можете плавать, вы можете умереть или что-то еще.. важно только то, что вам нужно иметь высоту (реализация в вашем классе)).
Ответ 5
Есть еще несколько отличий -
Интерфейсы не могут иметь конкретных реализаций. Абстрактные базовые классы могут. Это позволяет вам обеспечить конкретные реализации там. Это может позволить абстрактному базовому классу фактически обеспечить более строгий контракт, если интерфейс действительно описывает только то, как используется класс. (В абстрактном базовом классе могут быть не виртуальные члены, определяющие поведение, что дает больший контроль над автором базового класса.)
В классе может быть реализовано несколько интерфейсов. Класс может быть получен только из одного абстрактного базового класса. Это позволяет использовать полиморфную иерархию с использованием интерфейсов, но не абстрактных базовых классов. Это также позволяет использовать псевдо-множественное наследование с использованием интерфейсов.
Абстрактные базовые классы могут быть изменены в v2 + без нарушения API. Изменения в интерфейсах нарушают изменения.
[С#/.NET Specific] Интерфейсы, в отличие от абстрактных базовых классов, могут применяться к типам значений (structs). Структуры не могут наследоваться от абстрактных базовых классов. Это позволяет применять поведенческие контракты/правила использования для типов значений.
Ответ 6
наследование
Рассмотрим машину и автобус. Это два разных автомобиля. Но, тем не менее, они имеют некоторые общие свойства, такие как рулевое управление, тормоза, шестерни, двигатель и т.д.
Таким образом, с концепцией наследования это можно представить следующим образом...
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 own way to dial a number
}
}
Dialable PHONE2 = new Dialable() {
public void dial(Number n) {
//Do the phone2 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 и это единственное, о чем заботится функция.
Разработчики обычно используют интерфейсы для обеспечения взаимодействия (взаимозаменяемости) между объектами, поскольку они имеют общую функцию (точно так же, как вы можете перейти на стационарный или мобильный телефон, если вам просто нужно набрать номер). Короче говоря, интерфейсы - это гораздо более простая версия абстрактных классов без каких-либо свойств.
Также обратите внимание, что вы можете реализовать (наследовать) столько интерфейсов, сколько захотите, но вы можете расширять (наследовать) только один родительский класс.
Больше информации Абстрактные классы и интерфейсы
Ответ 7
Если вы рассматриваете java
как язык OOP для ответа на этот вопрос, выпуск Java 8 приводит к тому, что некоторые из приведенных выше ответов являются устаревшими. Теперь интерфейс java может иметь методы по умолчанию с конкретной реализацией.
Сайт Oracle предоставляет ключевые различия между interface
и abstract
классом.
Рассмотрим использование абстрактных классов, если:
- Вы хотите поделиться кодом между несколькими тесно связанными классами.
- Вы ожидаете, что классы, которые расширяют ваш абстрактный класс, имеют много общих методов или полей или требуют модификаторов доступа, кроме публичных (например, защищенных и приватных).
- Вы хотите объявить нестатические или нефинальные поля.
Рассмотрите возможность использования интерфейсов, если:
- Вы ожидаете, что не связанные классы будут реализовывать ваш интерфейс. Например, многие несвязанные объекты могут реализовывать интерфейс
Serializable
. - Вы хотите указать поведение конкретного типа данных, но не обеспокоены тем, кто реализует его поведение.
- Вы хотите использовать множественное наследование типа.
Проще говоря, я хотел бы использовать
interface: для реализации контракта несколькими несвязанными объектами
абстрактный класс: реализовать одно и то же или другое поведение между несколькими связанными объектами
Взгляните на пример кода, чтобы понять вещи понятным образом: как я должен объяснить разницу между интерфейсом и абстрактным классом?
Ответ 8
Интервьюеры лают странное дерево. Для таких языков, как С# и Java, есть разница, но на других языках, таких как С++, нет. Теория OO не отличает эти два, а просто синтаксис языка.
Абстрактный класс - это класс с реализацией и интерфейсом (чистые виртуальные методы), которые будут унаследованы. Интерфейсы обычно не имеют никакой реализации, а только чистые виртуальные функции.
В С# или Java абстрактный класс без какой-либо реализации отличается от интерфейса только в синтаксисе, используемом для его наследования, и в том, что вы можете наследовать только один.
Ответ 9
Используя интерфейсы, вы получаете композицию ( "has-a" ) вместо наследования (отношения "is-a" ). Это важный принцип, чтобы помнить, когда речь заходит о таких вещах, как шаблоны проектирования, где вам нужно использовать интерфейсы для достижения композиции поведения, а не наследования.
Ответ 10
я расскажу о деталях глубины интерфейса и абстрактном классе. Если вы знаете обзор интерфейса и абстрактного класса, тогда первый вопрос придет вам в голову, когда мы должны использовать интерфейс и когда мы должны использовать абстрактный класс.
Поэтому, пожалуйста, проверьте ниже описание интерфейса и абстрактного класса.
-
Когда мы должны использовать интерфейс?
если вы не знаете о реализации, у нас есть спецификация требований, тогда мы идем с интерфейсом
-
Когда мы должны использовать абстрактный класс?
если вы знаете реализацию, но не полностью (частично реализуете), тогда мы перейдем к классу Abstract.
Интерфейс
каждый метод по умолчанию public abstract означает, что интерфейс является абстрактным абстрактным 100%.
Абстрактный
может иметь метод Concrete и абстрактный метод, что такое метод Concrete, который имеет реализацию в абстрактном классе, Абстрактный класс - это класс, объявленный абстрактом - он может включать или не включать абстрактные методы.
Интерфейс
Мы не можем объявить интерфейс как закрытый, защищенный
Q. Почему мы не объявляем интерфейс приватным и защищенным?
Потому что метод интерфейса по умолчанию является публичным аннотатом, поэтому и поэтому мы не объявляем интерфейс приватным и защищенным.
Метод интерфейса
также мы не можем объявить интерфейс как закрытый, защищенный, конечный, статический, синхронизированный, родной.....
я приведу причину:
почему мы не объявляем синхронизированный метод, потому что мы не можем создать объект интерфейса и синхронизировать работу над объектом так, и сын рассуждает о том, что мы не объявляем синхронизированный метод
Переходная концепция также неприменима, поскольку переходная работа с синхронизированной.
Аннотация
мы с удовольствием используем публичный, закрытый конечный статический... означает, что ограничение не применимо в абстрактной форме.
Интерфейс
Переменные объявляются в интерфейсе как по умолчанию public static final, поэтому мы также не объявляем переменную как конфиденциальную, защищенную.
Изменчивый модификатор также не применим в интерфейсе, потому что переменная интерфейса по умолчанию является общедоступной статической конечной и конечной переменной, вы не можете изменить значение после назначения значения переменной, и как только вы объявили переменную в интерфейс, вы должны назначить переменную.
И переменная volatile сохраняет изменения, поэтому opp. к окончанию, это причина, по которой мы не используем переменную volatile в интерфейсе.
Абстрактный
Абстрактная переменная не нуждается в объявлении публичного статического окончательного.
Надеюсь, эта статья будет полезна.
Ответ 11
Концептуально говоря, сохранение специфической для языка реализации, правил, преимуществ и достижение какой-либо цели программирования с использованием кого-либо или обоих, может или не может иметь код/данные/свойство, бла-бла, однократное или множественное наследование, все в стороне
1- Аннотация (или чистый абстрактный) класс предназначен для реализации иерархии. Если ваши бизнес-объекты выглядят несколько структурно похожими, представляя родство с родительским (иерархическим) видом отношений, то будут использоваться только классы наследования/абстракции. Если ваша бизнес-модель не имеет иерархии, тогда наследование не должно использоваться (здесь я не говорю о логике программирования, например, некоторые шаблоны проектирования требуют наследования). Концептуально абстрактный класс - это метод реализации иерархии бизнес-модели в ООП, он не имеет ничего общего с интерфейсами, фактически сравнение абстрактного класса с интерфейсом бессмысленно, потому что оба концептуально совершенно разные вещи, в опросах попросят просто проверить потому что он выглядит как обеспечивающий несколько одинаковые функциональные возможности при реализации, и мы, программисты, обычно подчеркиваем больше о кодировании. [Имейте это в виду, что абстракция отличается от абстрактного класса].
2- Интерфейс - это контракт, полная функциональность бизнеса, представленная одним или несколькими наборами функций. Вот почему он реализован и не унаследован. Бизнес-объект (часть иерархии или нет) может иметь любое количество функциональных возможностей. Он не имеет ничего общего с абстрактными классами, т.е. означает наследование в целом. Например, человек может RUN, слон может RUN, птица может RUN и т.д., Все эти объекты различной иерархии будут реализовывать интерфейс RUN или интерфейс EAT или SPEAK. Не входите в реализацию, поскольку вы можете реализовать ее как имеющую абстрактные классы для каждого типа, реализующего эти интерфейсы. Объект любой иерархии может иметь функциональность (интерфейс), которая не имеет ничего общего с ее иерархией.
Я полагаю, что интерфейсы не были изобретены для достижения множественных наследований или для раскрытия публичного поведения, а также, чистые абстрактные классы не должны перегружать интерфейсы, а интерфейс - это функциональность, которую объект может выполнять (через функции этого интерфейса), а абстрактный класс представляет собой родительский элемент иерархии для создания детей, имеющих основную структуру (свойство + функциональность) родительского
Когда вас спрашивают о различии, на самом деле это концептуальная разница, а не различие в конкретной языковой реализации, если только не задано явно.
Я считаю, что оба интервьюера ожидали одной прямой прямой разницы между этими двумя, и когда вы потерпели неудачу, они попытались подтолкнуть вас к этой разнице, реализовав ОДИН как ДРУГОЙ
Что делать, если у вас был абстрактный класс с абстрактными методами?
Ответ 12
Для .Net,
Ваш ответ второму интервьюеру также является ответом на первый... Абстрактные классы могут иметь реализацию, а состояние, интерфейсы не могут...
EDIT: В другой заметке я бы даже не использовал фразу "подкласс" (или "наследование" ) для описания классов, которые "определены для реализации" интерфейса. Для меня интерфейс - это определение контракта, который должен соответствовать классу, если он был определен для реализации этого интерфейса. Это ничего не наследует... Вы должны добавить все сами, явно.
Ответ 13
Я думаю, что вам не понравился ваш ответ, потому что вы дали технические отличия вместо дизайнерских. Вопрос походит на вопрос тролля для меня. На самом деле интерфейсы и абстрактные классы имеют совершенно другой характер, поэтому вы не можете их сравнить. Я дам вам свое видение того, что является ролью интерфейса и какова роль абстрактного класса.
: используется для обеспечения контракта и обеспечения низкой связи между классами, чтобы иметь более поддерживаемое, масштабируемое и проверяемое приложение.
абстрактный класс: используется только для факторизации некоторого кода между классами той же ответственности. Обратите внимание, что это основная причина, по которой многократное наследование является плохой задачей в ООП, потому что класс не должен обрабатывать многие ответы (используйте composition).
Таким образом, интерфейсы имеют реальную архитектурную роль, тогда как абстрактные классы - это всего лишь деталь реализации (если вы используете его правильно, конечно).
Ответ 14
Интерфейс: должен использоваться, если вы хотите использовать правило для компонентов, которые могут или не могут быть связаны друг с другом
Плюсы:
- Позволяет множественное наследование
- Предоставляет абстракцию, не раскрывая, какой именно объект используется в контексте
- обеспечивает согласованность конкретной подписью контракта
Минусы:
- Необходимо реализовать все определенные контракты
- Не может быть переменных или делегатов
- После определения невозможно изменить без нарушения всех классов
Абстрактный класс: должен использоваться там, где вы хотите иметь базовое или стандартное поведение или реализацию для компонентов, связанных друг с другом
Плюсы:
- Быстрее, чем интерфейс
- Имеет гибкость в реализации (вы можете реализовать ее полностью или частично)
- Может быть легко изменено без разбиения производных классов
Минусы:
- Невозможно создать экземпляр
- Не поддерживает множественное наследование
Ответ 15
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?"
Docs ясно говорят, что если абстрактный класс содержит только объявления абстрактного метода, он должен быть объявлен как интерфейс.
An another interviewer asked me what if you had a Public variable inside
the interface, how would that be different than in Abstract Class?
Переменные в интерфейсах по умолчанию являются public static и final. Вопрос может быть сформулирован так, как если бы все переменные в абстрактном классе были общедоступными? Ну, они все равно могут быть не статичными и несинтевыми, в отличие от переменных в интерфейсах.
Наконец, я бы добавил еще одно замечание к упомянутым выше - абстрактные классы по-прежнему являются классами и попадают в одно дерево наследования, тогда как интерфейсы могут присутствовать в множественном наследовании.
Ответ 16
- Интерфейс:
- Мы не реализуем (или определяем) методы, мы делаем это в производных классах.
- Мы не объявляем переменные-члены в интерфейсах.
- Интерфейсы выражают связь HAS-A. Это означает, что они являются маской объектов.
- Абстрактный класс:
- Мы можем объявлять и определять методы в абстрактном классе.
- Мы скрываем его конструкторы. Это означает, что из него не создается никакого объекта.
- Абстрактный класс может содержать переменные-члены.
- Производные классы наследуют абстрактный класс, который означает, что объекты из производных классов не маскируются, он наследует абстрактный класс. Связь в этом случае - IS-A.
Это мое мнение.
Ответ 17
Скопировано из CLR через С# Джеффри Рихтером...
Я часто слышу вопрос: "Должен ли я создать базовый тип или интерфейс?" Ответ не всегда clearcut.
Вот некоторые рекомендации, которые могут вам помочь:
■■ Отношение IS-A к CAN-DO Тип может наследовать только одну реализацию. Если полученная
тип can not требует отношения IS-A с базовым типом, не использует базовый тип; используйте интерфейс.
Интерфейсы подразумевают связь CAN-DO. Если функция CAN-DO, по-видимому, принадлежит
с различными типами объектов, используйте интерфейс. Например, тип может преобразовывать собственные экземпляры
к другому типу (IConvertible), тип может сериализовать экземпляр самого себя (ISerializable),
и т.д. Обратите внимание, что типы значений должны быть получены из System.ValueType, и поэтому они не могут
быть производным от произвольного базового класса. В этом случае вы должны использовать связь CAN-DO
и определите интерфейс.
■■ Простота использования. Как правило, вам как разработчику проще определить новый тип, полученный из
базового типа, чем реализовать все методы интерфейса. Базовый тип может обеспечить
много функциональности, поэтому производный тип, вероятно, нуждается только в относительно небольших модификациях в своем поведении. Если вы предоставляете интерфейс, новый тип должен реализовывать все члены.
■■ Последовательная реализация Независимо от того, насколько хорошо документирован контракт на интерфейс, его
очень маловероятно, что каждый выполнит контракт на 100 процентов правильно. Фактически, COM
страдает от этой самой проблемы, поэтому некоторые COM-объекты работают корректно только с
Microsoft
Word или с Windows Internet Explorer. Предоставляя базовый тип с хорошим
по умолчанию, вы начинаете использовать тип, который работает и хорошо протестирован; вы можете тогда
изменить детали, которые нуждаются в модификации.
■■ Versioning Если вы добавите метод в базовый тип, производный тип наследует новый метод,
вы начинаете использовать тип, который работает, и исходный код пользователя даже не нужно перекомпилировать.
Добавление нового элемента в интерфейс заставляет наследника интерфейса изменять
его исходный код и перекомпилировать.
Ответ 18
Разница между интерфейсом Java и абстрактным классом
-
Основное различие заключается в том, что методы интерфейса Java неявно абстрактны и не могут иметь реализаций. Абстрактный класс Java может иметь методы экземпляра, которые реализуют поведение по умолчанию.
-
Переменные, объявленные в интерфейсе Java, по умолчанию являются окончательными. Абстрактный класс может содержать не конечные переменные.
-
Члены интерфейса Java по умолчанию являются общедоступными. Абстрактный класс Java может иметь обычные вкусы членов класса, таких как частные, защищенные и т.д.
-
Интерфейс Java должен быть реализован с использованием ключевого слова "инструменты"; Абстрактный класс Java должен быть расширен с использованием ключевого слова "extends".
-
Интерфейс может расширить только другой интерфейс Java, абстрактный класс может расширить другой класс Java и реализовать несколько интерфейсов Java.
-
Java-класс может реализовывать несколько интерфейсов, но может расширять только один абстрактный класс.
-
Интерфейс абсолютно абстрактен и не может быть создан; Явный абстрактный класс также не может быть создан, но может быть вызван, если существует main().
-
По сравнению с абстрактными классами Java, java-интерфейсы медленны, так как требуют дополнительной косвенности.
Ответ 19
Интерфейс определяет контракт на услугу или набор сервисов. Они обеспечивают полиморфизм горизонтальным образом, поскольку два полностью несвязанных класса могут реализовывать один и тот же интерфейс, но использоваться взаимозаменяемо как параметр типа интерфейса, который они реализуют, поскольку оба класса обещали удовлетворить набор сервисов, определенных интерфейсом. Интерфейсы не предоставляют деталей реализации.
Абстрактный класс определяет базовую структуру для своих подкасс и необязательную частичную реализацию. Абстрактные классы обеспечивают полиморфизм вертикальным, но направленным образом, поскольку любой класс, наследующий абстрактный класс, можно рассматривать как экземпляр этого абстрактного класса, но не наоборот. Абстрактные классы могут и часто содержат детали реализации, но не могут быть созданы самостоятельно, только их подклассы могут быть "обновлены".
С# также позволяет наследовать интерфейс.
Ответ 20
В большинстве ответов основное внимание уделяется технической разнице между абстрактным классом и интерфейсом, но поскольку технически интерфейс в основном является своего рода абстрактным классом (без каких-либо данных или реализации), я думаю, что концептуальная разница гораздо интереснее, и это может быть то, что делают интервьюеры.
Интерфейс - это соглашение. Он указывает: "так мы будем разговаривать друг с другом". Он не может иметь никакой реализации, поскольку он не должен иметь никакой реализации. Это контракт. Это как заголовочные файлы .h
в C.
Абстрактный класс - это неполная реализация. Класс может или не может реализовывать интерфейс, а абстрактный класс не должен реализовывать его полностью. Абстрактный класс без какой-либо реализации является бесполезным, но вполне законным.
В принципе любой класс, абстрактный или нет, о том, что это такое, тогда как интерфейс касается того, как вы его используете. Например: Animal
может быть абстрактным классом, реализующим некоторые основные метаболические функции и определяющим абстрактные методы для дыхания и локомоции, не давая им реализации, потому что он не знает, нужно ли ему дышать через жабры или легкие, и летает ли он, плавает, гуляет или ползает. Mount
, с другой стороны, может быть интерфейсом, который указывает, что вы можете кататься на животном, не зная, какое это животное (или это вообще животное!).
Тот факт, что за кулисами интерфейс - это в основном абстрактный класс с абстрактными методами, не имеет значения. Концептуально они выполняют совершенно разные роли.
Ответ 21
Как вы могли бы получить теоретические знания от экспертов, я не трачу много слов на повторение всех здесь, а позвольте мне объяснить с помощью простого примера, где мы можем использовать/не можем использовать Interface
и Abstract class
.
Учтите, что вы разрабатываете приложение для перечисления всех функций автомобилей. В разных точках вам необходимо наследовать, так как некоторые свойства, такие как DigitalFuelMeter, Air Conditioning, регулировка сиденья и т.д., Являются общими для всех автомобилей. Аналогично, нам нужно наследование для некоторых классов только в том случае, если некоторые из свойств, таких как тормозная система (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). Хотя оба используют технологию торможения, "технология" отличается. Таким образом, мы создаем абстрактный класс, в котором метод будет объявлен как абстрактный, и он должен быть реализован в его дочерних классах.
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";
}
}
См. проблему в двух предыдущих классах? Они наследуют от нескольких классов, которые С#.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 могут добиться множественного наследования с помощью своих технологий торможения с помощью интерфейса.
Ответ 22
Интерфейсы - это легкий способ обеспечить соблюдение определенного поведения. Это один из способов подумать.
Ответ 23
Абстрактный класс и разница в интерфейсе:
- Абстрактный класс может иметь абстрактные и не абстрактные методы, а интерфейс может иметь только абстрактные методы.
- Абстрактный класс не поддерживает множественное наследование. Интерфейс поддерживает множественное наследование.
- Абстрактный класс может иметь конечные, не конечные, статические и нестатические переменные. Интерфейс имеет только статические и конечные переменные.
- Абстрактный класс может иметь статические методы, основной метод и конструктор. Интерфейс не может иметь статические методы, основной метод или конструктор.
- Абстрактный класс может обеспечить реализацию интерфейса. Интерфейс не может обеспечить реализацию абстрактного класса.
- Ключевое слово abstract используется для объявления абстрактного класса И Ключевое слово интерфейса используется для объявления интерфейса.
- Абстрактный класс достигает частичной абстракции (от 0 до 100%), потому что в абстрактном классе также существуют абстрактные методы, тогда как интерфейс достигает полной абстракции (100%).
Ответ 24
1) Интерфейс можно рассматривать как чистый абстрактный класс, тот же, но, несмотря на это, не то же самое, чтобы реализовать интерфейс и наследовать от абстрактного класса. Когда вы наследуете этот чистый абстрактный класс, вы определяете иерархию → наследование, если вы реализуете интерфейс, которого вы нет, и вы можете реализовать столько интерфейсов, сколько хотите, но вы можете наследовать только один класс.
2) Вы можете определить свойство в интерфейсе, поэтому класс, реализующий этот интерфейс, должен иметь это свойство.
Например:
public interface IVariable
{
string name {get; set;}
}
Класс, реализующий этот интерфейс, должен иметь такое свойство.
Ответ 25
Ответ на второй вопрос: public
переменная, определенная в interface
, static final
по умолчанию, тогда как переменная public
в классе abstract
является переменной экземпляра.
Ответ 26
Хотя этот вопрос довольно старый, я хотел бы добавить еще один аргумент в пользу интерфейсов:
Интерфейсы могут быть инъецированы с использованием любых инструментов инжекции зависимостей, где в качестве абстрактной инъекции классов поддерживается очень мало.
Ответ 27
Типы интерфейса и абстрактные базовые классы
Адаптировано из Pro С# 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(). Если вы создадите новый набор классов, которые не расширяют этот базовый класс, вы не сможете получить этот полиморфный интерфейс. Также вы можете вспомнить, что С# не поддерживает множественное наследование классов. Поэтому, если вы хотите создать 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();
}
Ответ 28
Из другого моего ответа, в основном касающегося того, когда использовать один и другой:
По моему опыту, интерфейсы лучше используется, когда у вас есть несколько классов каждый из которых должен реагировать на одно и то же метода или методов, чтобы они могли быть используется взаимозаменяемо другим кодом которые будут классов. Лучший использование интерфейса - это когда протокол имеет важное значение, но базовая логика может отличаться для каждый класс. Если бы вы были в противном случае дублирующая логика, рассмотрим абстрактную классы или наследование стандартного класса вместо этого.
Ответ 29
Конечно, важно понимать поведение интерфейса и абстрактного класса в ООП (и как их обрабатывают языки), но я думаю, что также важно понять, что именно означает каждый термин. Можете ли вы представить, что команда if
не работает точно так же, как смысл этого термина? Кроме того, на самом деле некоторые языки уменьшают, тем более, различия между интерфейсом и абстрактным... если случайно в один прекрасный день два термина работают почти одинаково, по крайней мере, вы можете определить, где (и почему) должен быть какой-либо из них используется для.
Если вы читаете некоторые словари и другие шрифты, вы можете найти разные значения для одного и того же термина, но с некоторыми общими определениями. Я думаю, что эти два значения, которые я нашел на этом сайте, действительно, действительно хороши и подходят.
Интерфейс:
Вещь или обстоятельство, которое позволяет отдельным и иногда несовместимым элементам эффективно координировать свои действия.
Абстрактные:
Что-то, что концентрирует в себе существенные качества чего-либо более обширного или более общего или нескольких вещей; сущность.
Пример:
Вы купили автомобиль, и ему нужно топливо.
Ваша модель автомобиля - XYZ
, которая относится к жанру ABC
, поэтому это конкретный автомобиль, конкретный экземпляр автомобиля. Автомобиль не настоящий объект. Фактически, это абстрактный набор стандартов (качеств) для создания определенного объекта. Короче говоря, Car является абстрактным классом, это "то, что концентрирует в себе существенные качества любого более обширного или более общего".
Единственное топливо, которое соответствует спецификации руля автомобиля, должно использоваться для заполнения автоцистерны. В действительности, вам нечего ограничивать, чтобы топливо было включено, но двигатель будет работать правильно только с указанным топливом, поэтому лучше следовать его требованиям. В требованиях говорится, что он принимает, как и другие автомобили того же жанра ABC
, стандартный набор топлива.
В объектно-ориентированном виде топливо для жанра ABC
не следует объявлять как класс, потому что нет конкретного топлива для определенного жанра автомобиля. Хотя ваш автомобиль может принять абстрактный класс Fuel или vehicleularFuel, вы должны помнить, что ваш единственный из существующих автомобильных топлив соответствует спецификации, которые соответствуют требованиям в вашем руководстве по автомобильному оборудованию. Короче говоря, они должны реализовать интерфейс ABCGenreFuel
, который "... позволяет отдельным и иногда несовместимым элементам эффективно координировать".
добавление
Кроме того, я думаю, вы должны иметь в виду значение термина class, который (с того же сайта, который упоминался ранее):
Класс:
Ряд лиц или вещи, которые считаются образующими группу по общим признакам, характеристикам, качествам или чертам; своего рода;
Таким образом, класс (или абстрактный класс) не должен представлять только общие атрибуты (например, интерфейс), а некоторую группу с общими атрибутами. Интерфейс не должен представлять вид. Он должен представлять общие атрибуты. Таким образом, я думаю, что классы и абстрактные классы могут использоваться для представления вещей, которые не должны часто изменять его аспекты, как человек, млекопитающий, потому что он представляет некоторые виды. Виды не должны часто меняться.
Ответ 30
С точки зрения кодирования
Интерфейс может заменить абстрактный класс, если абстрактный класс имеет только абстрактные методы. В противном случае изменение абстрактного класса на интерфейс означает, что вы будете проигрывать при повторном использовании кода, который предоставляет Inheritance.
С точки зрения дизайна
Сохраняйте его как абстрактный класс, если это отношение "есть", и вам нужно подмножество или все функциональные возможности. Держите его как интерфейс, если он "должен делать".
Решите, что вам нужно: просто политическое принуждение или политика повторного использования кода.