Каковы отличия между абстрактным классом и интерфейсом?
Ответы
Ответ 1
Короткое различие.
Абстрактный класс — это класс, у которого не реализован один или больше методов (некоторы
языки требуют такие методы помечать специальными ключевыми словами).
Интерфейс — это абстрактный класс, у которого ни один метод не реализован, все он
публичные и нет переменных класса.
Интерфейс нужен обычно когда описывается только интерфейс (тавтология). Например
один класс хочет дать другому возможность доступа к некоторым своим методам, но не хоче
себя «раскрывать». Поэтому он просто реализует интерфейс.
Абстрактный класс нужен, когда нужно семейство классов, у которых есть много общего
Конечно, можно применить и интерфейс, но тогда нужно будет писать много идентичного кода.
В некоторых языках (С++) специального ключевого слова для обозначения интерфейсов нет.
Можно считать, что любой интерфейс — это уже абстрактный класс, но не наоборот.
Ответ 2
tl;dr: Абстрактный класс — средство разработки классов на нижнем уровне, средств
для повторного использования кода; интерфейс — средство выражения семантики класса
Таким образом, это совершенно разные, мало связанные между собой понятия.
Думайте об этом по-другому.
Абстрактный класс — это «заготовка» класса: реализовано большинство методов (включа
внутренние), кроме нескольких. Эти несколько нереализованных методов вполне могут быт
внутренними методами класса, они лишь уточняют детали имплементации. Абстрактный клас
— средство для повторного использования кода, средство, чтобы указать, какой метод обяза
быть перекрыт для завершения написания класса.
Интерфейс же — это своего рода контракт: интерфейсы используются в определениях чтоб
указать, что объект, который будет использован на самом деле, должен реализовывать (дл
входных параметров) или будет гарантированно реализовывать (для выходных параметров
набор методов и (что намного важнее!) иметь определённую семантику. Интерфейс вполн
может быть и пустым, тем не менее, имплементировать интерфейс означает поддерживат
данную семантику.
Абстрактные классы идеологически схожи с шаблонами C++: и те, и другие являются заготовкам
классов, но шаблону для получения класса нужно специфицировать шаблонные типы, а абстрактном
классу — абстрактные методы.
Интерфейсы идеологически схожи с заголовочными файлами C++: они раскрывают метод
и скрывают конкретную реализацию.
Вопрос о том, является ли интерфейс или абстрактный класс собственно классом — техническа
подробность реализации, зависящая от конкретного языка программирования. Например,
C++ интерфейсы отсутствуют вовсе, и их приходится эмулировать классами без данных. Абстрактны
класс в C++ как таковой также отсутствует, но им можно считать любой класс с абстрактным
методами. (Отсюда ограничение C++: как минимум 1 абстрактный метод в абстрактном классе.
Также в C++ можно (непрямо) инстанциировать абстрактный класс, вызвать абстрактный мето
и (возможно) получить ошибку времени выполнения. В C# интерфейсы и абстрактные класс
встроены в язык.
Пример (на C#, конкретный язык значения не имеет):
// общий код для всех животных
abstract class АбстрактноеЖивотное
{
public int Возраст { get; protected set; }
public int Вес { get; protected set; }
public bool Спит { get; protected set; }
public void ПодатьГолос()
{
if (!Спит && Возраст > ВозрастПрорезанияГолоса)
РеализацияПодатьГолос();
}
abstract protected void РеализацияПодатьГолос();
readonly protected int ВозрастПрорезанияГолоса;
}
class Собака : АбстрактноеЖивотное
{
override protected void РеализацияПодатьГолос()
{
Гав();
}
public void Гав()
{
// реализация
}
public Собака() { ВозрастПрорезанияГолоса = 2; }
}
class Кошка : АбстрактноеЖивотное
{
override protected void РеализацияПодатьГолос()
{
Мяу();
}
public void Мяу()
{
// реализация
}
public Кошка() { ВозрастПрорезанияГолоса = 1; }
}
interface IЖивотное
{
int ИнвентарныйНомер { get; }
}
class Лев : ОбитательЗоопарка, IЖивотное
{
// ...
}
class Зебра : ОбитательЗоопарка, IЖивотное
{
// ...
}
class Сторож : ОбитательЗоопарка
{
}
// ...
void Инвентаризация()
{
List<ОбитательЗоопарка> обитатели = // ...
foreach (var обитатель in обитатели)
if (обитатель is IЖивотное) // отделяем животных от неживотных
ДобавитьЖивотное((IЖивотное)обитатель);
}
void ДобавитьЖивотное(IЖивотное животное) // сюда сможет попасть только животное
{
...
Ответ 3
Мне кажется достаточно любопытным, что данный вопрос помечен тегом «ооп», но пр
этом во многих ответах явно просачиваются специфические аспекты конкретных языков программирования
Я же постараюсь дать ответ исходя из понятий ООП и лишь потом показать, почему вообщ
это различие появилось в некоторых языках программирования.
Абстрактные классы и интерфейсы имеют определенное отношение к наследованию, точне
к моделированию мира. С их помощью мы хотим выразить, что у определенной группы веще
в нашей системе есть что-то общее: некоторое общее поведение, которое отличает эту групп
штуковин от всех остальных.
Допустим, для примера, мы хотим смоделировать кнопки в интерфейсе пользователя. Поскольк
мы говорим об ООП, то мы выделим некоторый тип Кнопки с некоторым набором операций (которы
определяют поведение) и скрытого состояния, на которое опирается поведение (да, скрытог
состояния может и не быть). При этом мы можем выделить три вида операции:
Конкретная фиксированная операция, которая должна быть абсолютно стабильно для все
типов кнопок.
Конкретная операция с поведением по умолчанию (т.е. операция, чье поведение подходи
для многих типов кнопок, но могут быть кнопки с другим поведением).
Декларация операции без конкретной реализации (т.е. операция, чье поведение определит
невозможно, поскольку на этом этапе не известно разумное поведение по умолчанию ил
же операции могут слишком сильно различаться у разных кнопок).
Другими словами, тип Кнопки может содержать невиртуальные методы (non-virtual methods)
виртуальные методы (virtual methods) и абстрактные методы (abstract methods).
Наличие разных типов методов является очень важным инструментом моделирования и позволяе
весьма точно выражать намерения проектировщика. Например, мы можем добавить невиртуальну
операцию «Нажатия на кнопку», которая будет делегировать часть своей работы виртуальном
(или абстрактному методу) «Обработать нажатие», но при этом всегда выполнять определенну
часть работы (прозорливый читатель увидит в этом описании паттерн «Шаблонный метод»).
После того, как мы определили базовый тип, пришло время определить произвольные типы
И тут начинаются вопросы. Точнее, вопросов никаких не возникает, когда у типа есть лиш
один непосредственный базовый тип или все базовые типы содержат лишь декларации операций
Не проблема, унаследовать «Кнопку меню» от «Кнопки» и переопределить метод «Нажать н
кнопку». Но что, если наш тип «Кнопка меню» будет отнаследован от двух типов с одно
и той же виртуальной операцией? Как переопределить лишь одну, а оставить другую? А ка
быть клиенту нового типа и различить, какую операцию вызвать? А что если у двух базовы
типов есть поле с одним именем? А что если у одного базового типа метод «Нажать кнопку
реализован, а у другого – лишь описан в виде декларации?
Нет, все эти проблемы решаемы, и в С++, и Eiffel, и других языках программировани
вы можете довольно гибко контролировать, что и как переопределять, что прятать, чт
выставлять наружу и как вызвать метод определенного базового типа. Но для авторов некоторы
языков программирования подобная сложность показалась излишней, и они пошли на хитрост
и отделили типы, которые содержат лишь декларации методов в отдельную категорию, и та
появились интерфейсы.
Теперь будет легко провести разницу между тремя понятиями – интферфейса, абстрактног
базового класса и конкретного базового класса.
Интерфейс – описывает некоторое семейство типов и содержит лишь декларации операци
(да, я осознанно пишу слово «декларация», а не использую слово «контракт», которое
ООП имеет вполне определенное значение).
Абстрактный базовый класс описывает некоторое семейство типов, но помимо деклараци
операций может содержать реализации по умолчанию (виртуальные методы) и фиксированны
операции (невиртуальные методы).
Конкретный класс описывает некоторое семейство типов, которое готово для использовани
клиентами. Такой класс не может содержать декларации операций и все его операции должн
быть либо фиксированными (невиртуальные методы) или содержать реализацию по умолчани
(виртуальные методы). Есть еще один подвид конкретных классов – запечатанный (sealed
класс – это разновидность конкретного класса отнаследоваться от которого невозможно
а значит он может содержать лишь конкретные операции.
Выделение интерфейсов в отдельную категорию полезно не только с точки зрения упрощени
реализации языков программирования, но и для выделения разных подходов к моделированию
Так, например, наследование классов моделирует отношение «Является» («Кнопка меню» ЯВЛЯЕТС
«Кнопкой»), а базовые классы обычно содержат определенный функционал, тесно связанны
с функционалом производного класса. Базовые классы не просто моделируют группу типов
но и позволяют использовать повторно существующий функционал.
Интерфейсы же, по своей природе обладают меньшей связностью (low coupling), поскольк
не обладают конкретным поведением, которое может осложнить жизнь класса-наследника
Интерфейсы также могут моделировать отношение «Является» («Кнопка меню» ЯВЛЯЕТСЯ «IКнопкой»)
но могут определять и менее жесткое отношение «Может выполнять роль» (CAN DO). Например
интерфейс IEquatable из BCL определяет «дополнительное» поведение, которое говорит
возможности типов сравнивать значения объектов.
Ответ 4
Давайте по порядку. Интерфейс - это договор/объязательства, которые берёт на себ
класс и обязан их выполнить. Допустим: есть массив классов, которые умеют здороваться
std::vector mArr;
class IHellower{
virtual void Hello() = 0;
}
Теперь любой класс вне зависимости от его сложности иерархии и объема может унаследоват
(взять на себя объязательство/подписать контракт на выполнения) данного метода и те
самым "станет своим через чужих". Самое приятное тут то, что каким бы обширным бы н
был интерфейс (в данном контексте имеются публичные методы класса) у класса выполняющег
данный контракт - из этого массива будет видет только один метод. Пример: есть мног
графических классов и некоторые из них вы научили реагировать на Blur - запихните и
в 1 массив интерфейсов и при надобности вызывайте метод Blur(int value);
При использовании интерфейса, мы абстрагируемся от того, что за класс: машина
растение, воздух ... Если он взял на себя обязательства иметь реализацию "Поздороваться
у нас есть гарантия, что данный метод будет нам доступен через объект (указатель данног
класса) (напоминаю, интерфейс чистовиртуальные методы, в паблик секции, без переменных).
А теперь другая стороная, С++ при всём своем могуществе не имеет понятия интерфей
на уровне языка. Но программисты привыкли к интерфейсу, это удобно, это безопасно (почитайт
про Insersion of control) и правильно (с точки зрения архитектуры). Приходится реализовыват
"интерфейс" теми инструментами, что предлагает язык С++ - это абстракный класс. Ка
вы заметили, туда можно запихнуть разные методы (public/protected/private), класс-мемберов(
других языках за переменные в интерфейсе уже проблемы). Было бы ключевое слово interfac
в С++ и наследовалось бы внятно как в C# - такой бы путаницы небыло.
Абстрактные классы, как раз, и применяются в случаях выделения общей части классов
но самого такого класса как бы не должно быть (это бессмыслено иметь экземпляр таког
класа).
class SomeThingLikeABall
{
private:
int radius;
int weight;
public:
bool canPlayFootballWithIt() = 0;
void draw() = 0;
}
Как пример, описывали классы мяч и арбуз, нашли общие черты, увидели, что еще буду
описывать круглые предметы. Выделили всё это в общий класс и сделали его абстрактным
потому что зачем в системе иметь возможность иметь класс "Нечто кругло, с весом и можн
кинуть".
Ответ 5
Отличия абстрактного класса от интерфейса в Java
Ответ 6
Можно еще добавить, что часто класс описывает некоторую модель, а интерфейс - поведени
или роль. Класс называют существительным именем (Dog, Car, House), а к интерфейсу добавляю
окончание -able, чтобы описывало некоторое действие или свойство (Moveable, Eatable
Buildable). Например, мы создаем игру в жанре стратегия. У нас есть разные фракции
в каждой из них есть разные юниты (воины, строители) и мы для каждого юнита создае
отдельный класс. Но в поведении между всеми этими юнитами есть много общего - у любог
воина независимо от фракции есть способность драться (Attackable), у любого строител
независимо от фракции есть способность строить (Buildable), а у абсолютно всех юнито
есть способность двигаться (Moveable). Таким образом можно описать взаимодействие все
ролей с помощью множественного наследования интерфейсов.
Ответ 7
Можно я влезу )
класс с виртуальной функцией/функциями называется - абстрактным
абстрактный класс может иметь одну или несколько чисто виртуальных функций
если абстрактный класс имеет хотя бы одну чисто виртуальную функцию, объект таког
класса нельзя создавать, а только наследовать причем чисто виртуальные функции должн
быть переопределены в будущем.
интерфейс класса - это указание/договор с программистом о том, как программист може
использовать этот класс. т.е. получается интерфейс - это все открытые (public) данны
к которым может обратится программист.
по сути написал что и @VladD только простым языком
ps - модераторам почему я комментировать не могу?
Ответ 8
Абстрактный класс может иметь переменные, конструкторы, свойства и реализации методов
Интерфейс - только сигнатуры методов.
Ответ 9
В некоторых языках(Java ... ) возможно наследование от нескольких интерфейсов, н
только от 1-го класса.
Interface не реализовывает методы, а только предоставляет права доступа для их использовани
(Можно представить себе интерфейс - как вуаль или контракт на права доступа к чему-то)
В абстрактном классе вы можете реализовать метод и переопределить его в наследуемо
класе, просто вы не можете создавать объекты этого класа.
Ответ 10
Interface - это класс, который по умолчанию является абстрактным. По сути интерфей
нужен для того, чтобы от него наследоваться.
Ответ 11
Я в ООП новичок, но осмелюсь высказать свою версию происходящего.
Сначала программисты изобрели «интерфейсы» - так как это вещь в ООП очень удобная
И тут внезапно выяснилось, что некоторые разные классы, реализующие один и тот же интерфейс
могут содержать практически одинаковые куски кода! А раскидывать одни и те же куск
кода по разным местам проекта – это уже не есть хорошо. И тут изобрели «абстрактны
класс», который может выполнять не только роль интерфейса, но и служить сущностью дл
выделения общих участков кода – т.е. выполнять ту работу, которую не смог бы выполнит
интерфейс. Т.е. «абстрактный класс» помогает избежать дублирования кода – ведь одн
из главных методик работы программиста – умение находить общие участки кода и «выносит
их за скобки», так сказать, что способствует уменьшению дублирования кода. Т.е. в основ
всего этого лежит борьба со сложностью разработки и сопровождения программ и «абстрактны
класс» помогает решать эту задачу.
Ответ 12
Что такое абстрактный класс?
Абстрактный класс - это класс, который объявляется абстрактным - может включать ил
не включать абстрактные методы. Абстрактные классы не могут быть созданы, но они могу
быть подклассами. Когда абстрактный класс является подклассом, подкласс обычно предоставляе
реализации для всех абстрактных методов в его родительском классе.
Я немного расшифрую понятие абстрактного класса. В связи с вопросом почему я использу
абстрактный класс. Иногда я просто добавляю фразу abstract к классу, по причине тог
что некоторые методы должны имплементироваться пользоватем этого класса и указываю каки
иммено методы должны быть абстрактными. Для чего это нужно, впрочем если пользовател
будет пользоваться абстрактными классом, то часть его методов уже имеет дефолтную имплементацию
которую можно перекрыть, а абстрактные методы также перекрываются, только синтакси
предполагает наличие модификатора abstract и отсутствие тела метода, определяя тем самы
только сигнатуру. Это свойство языка и отличие от других объектно-ориентированных языков
Фраза abstract не обязательно предполагает абстрактность или такое толкование, а лиш
возможность указания методов, которые необходимо перекрывать в классах наследниках.
Что такое абстракция в программировании?
В объектно-ориентированном программировании абстракция является одним из трех основны
принципов (наряду с инкапсулированием и наследованием). Благодаря процессу абстракци
программист скрывает все, кроме соответствующих данных об объекте, чтобы уменьшить сложност
и повысить эффективность.
Может ли абстрактный класс не иметь абстрактных методов?
Да, мы можем иметь абстрактный класс без абстрактных методов, поскольку оба являютс
независимыми понятиями. Объявление абстрактного класса означает, что он не может быт
создан сам по себе и может быть только подклассифицирован. Объявление абстрактного метод
означает, что метод будет определен в подклассе.
Можете ли вы создать объект абстрактного класса в Java?
Если мы создадим объект абстрактного класса и назовем метод без тела (поскольку мето
является чисто виртуальным), он даст ошибку. Вот почему мы не можем создать объект абстрактног
класса. Короче говоря, законно иметь публичный конструктор абстрактного класса. Абстрактны
класс нельзя создать, но можно пользоваться если есть соответствующая имплементаци
этого класса. Сама абстракция в отличие от наследования предполагает отсутствие код
имплементации. Если вы используете абстрактный класс то вы можете ограничиться декларирование
методов. Интерфейсы это такие абстрактные классы у которых все методы абстрактные.
Комментариев нет:
Отправить комментарий