суббота, 25 октября 2008 г.

Абстрактный класс VS интерфейс

Недавно меня озадачили вопросом: чем отличается абстрактный класс от интерфейса в С++? Я вроде бы не настолько забыл С++, что бы помнить об абстрактных классах, но не помнить об интерфейсах.

В С++ есть понятие абстрактного класса - класс, у которого есть хотя бы одна чисто виртуальная функция и, соответственно, нельзя создать объект этого класса. Иногда еще говорят о чисто абстрактных классах, у которых все функции чисто виртуальные, но это скорее искусственное понятие, в большинстве случаев ничем не отличающееся от просто абстрактных классов.

Ни о каких интерфейсах в стандарте С++ не говориться, кроме того, что абстрактный класс может предоставлять интерфейс, который реализуется наследниками (10.4.1):

An abstract class can also be used to define an interface for which derived classes provide a variety of implementations.

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

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

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

Рекомендую к прочтению: Доступность действия в любой момент - оправдание не делать его вообще, Эффект осознания, Парадоксальные заповеди

1 комментарий:

Unknown комментирует...

Интерфейс и абстрактный класс - по сути две различные сущности в ООП.

Для начала стоит разделить само понятие "Интерфейс", которое имеет две стороны. С одной стороны, интерфейс, это неотделимая (встроенная) часть класса состоящая из всех публичных методов и свойств которые предоставляются в распоряжение пользователю класса.
Интерфейсом в этом понимании обладают и обычные классы и абстрактные.

Вторая "сторона медали" интерфейса, это определённая в Объектно Ориентированном Проектировании сущность похожая на класс, но содержащая декларации методов без их реализации. Причем никаких свойств, т.е. атрибутов интерфейс не имеет. Другими словами, интерфейс отвечает только на вопрос "Что я могу делать?".

Абстрактный класс по своей природе, это все же именно класс, который участвует в наследственной иерархии. Конкретизируясь в потомках. Т.е. по сути отвечает на вопрос "Кто я?".

Так что абстрактные классы, (как единица проектирования, а не как единица синтаксиса C++) предназначены для использования в родственных иерархиях.
А интерфейсы, в качестве классов-примесей определяющих специфический набор методов и не привязанных к наследственной иерархии.

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

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