Вкратце
Абстрактный класс — это класс, у которого не реализован один или больше методов (некоторые языки требуют такие методы помечать специальными ключевыми словами).
Интерфейс — это абстрактный класс, у которого ни один метод не реализован, все они публичные и нет переменных класса.
Интерфейс нужен обычно когда описывается только интерфейс (тавтология). Например, один класс хочет дать другому возможность доступа к некоторым своим методам, но не хочет себя «раскрывать». Поэтому он просто реализует интерфейс.
Абстрактный класс нужен, когда нужно семейство классов, у которых есть много общего. Конечно, можно применить и интерфейс, но тогда нужно будет писать много идентичного кода.
В некоторых языках (С++) специального ключевого слова для обозначения интерфейсов нет.
Можно считать, что любой интерфейс — это уже абстрактный класс, но не наоборот.
Отличия абстрактного класса от интерфейса в Java
Концептуально
-
Абстрактный класс — это «заготовка» класса: реализовано большинство методов (включая внутренние), кроме нескольких. Эти несколько нереализованных методов вполне могут быть внутренними методами класса, они лишь уточняют детали имплементации. Абстрактный класс — средство для повторного использования кода, средство, чтобы указать, какой метод обязан быть перекрыт для завершения написания класса.
-
Интерфейс — это своего рода контракт: интерфейсы используются в определениях чтобы указать, что объект, который будет использован на самом деле, должен реализовывать (для входных параметров) или будет гарантированно реализовывать (для выходных параметров) набор методов и (что намного важнее!) иметь определённую семантику. Интерфейс вполне может быть и пустым, тем не менее, имплементировать интерфейс означает поддерживать данную семантику.
Отличие абстрактного класса от интерфейса (4)
Абстрактный класс |
Интерфейс |
|
---|---|---|
Ключевое слово для описания |
abstract class |
interface |
Ключевое слово для реализации |
extends (расширяет) |
implements (реализует) |
Объявление конструктора |
Разрешено |
Запрещено |
Реализация методов по умолчанию |
Разрешена (но 1 и более методов абстрактны) |
Запрещена (все методы абстрактны) |
Поля данных |
Могут быть, любые |
Не могут быть |
Модификаторы доступа к методам |
Могут быть разными |
Только public |
Статичные методы |
Только методы, содержащие реализацию, могут быть объявлены статическими |
Не допустимы |
Область применения |
когда есть некоторые общие черты, которые должны быть общими для всех объектов. |
когда все функции должны быть реализованы по-разному для разных объектов |
Использование интерфейсов и абстрактных классов (примеры)
Пример №1
Интерфейс описывает свойства. Обратите внимание на классические названия интерфейсов: Throwable, Countable, Comparable, Iterable и т.д.
Возьмем, к примеру, интерфейс Rollable (катящийся), и Foldable (складывающийся).
Абстрактный класс же описывает сущность. Например, стол: Table_Abstract. Стол может быть деревянным, тогда будет Table_Wood extends Table_Abstract. Также стол может быть хирургическим: Table_Surgical extends Table_Abstract. В таком случае Table_Abstract объединяет общий свойства всех столов (скажем, площадь поверхности, наличие ножек и т.п.). А конкретный класс описывает сущность определенного типа столов.
Связью же интерфейсов и классов Вы описываете свойства. Например, стол можно катить: Table_Abstract implements Rollable. Деревянный стол, например, можно сложить: Table_Wood implements Foldable.
Пример №2
Интерфейс определяет функциональные возможности, поведение — «что именно следует делать, но не как это делать» (3). В абстрактном классе «определяется лишь самая общая форма для всех его производных классов, а наполнение ее деталями предоставляется каждому из этих классов» (2).
Простой пример, в контексте графического редактора можно определить:
-
Абстрактный класс — Figure (геометрическая фигура), от него могут быть образованы классы конкретных фигур — например, Rectangle, Circle и т.д.
-
Интерфейс — Drawable (то, что можно нарисовать). Он может быть реализован как во всех классах конкретных фигур (Circle, Rectangle), так и в других классах, не образованных от абстрактного Figure.
Пример №3
Интерфейсы надо использовать, когда классы, которые должны предоставлять один и тот же интерфейс, не должны быть (или не могут быть) связаны иерархически. (2)
Кроме того, если нужно предоставить несколько интерфейсов, а множественного наследования нет (как в PHP), то интерфейсы — единственный выход.
Пример №4
Интерфейс представляет набор сигнатур функций, которые необходимо реализовать при имплементации. Это не класс, это отдельная сущность. реализация методов в конкретных классах может быть абсолютно различной. общей является только сигнатура метода. в интерфейсе не может быть свойств (полей, констант). (2)
Абстрактный класс предполагает наличие как сигнатур, так и некой реализации по умолчанию для некоторых методов (как писали выше, это возможность вынести дублирующийся код). он используется при наследовании, в дочерних классах можно переопределить методы, а можно оставить реализацию самого абстрактного класса. абстрактный класс определяет общее поведение для объектов одного типа, в отличие от интерфейса, который может использоваться в классах различных не связанных между собой объектов.
Нельзя инициализировать объект абстрактного класса — это отличие от использования обычного класса для наследования.
Соответственно нужно учитывать, что при добавлении новой сигнатуры метода в интерфейс, его придется реализовать во всех классах, которые используют данный интерфейс. в абстрактном классе можно реализовать общее поведение по умолчанию для дочерних классов.
Источники:
(2) https://qna.habr.com/q/10682
(3) Г.Шилдт, Полное руководство C#)
(4) https://www.scorp13.com/workflow/raznica-mezhdu-abstraktnym-klassom-i-interfeysom-v-php.html
Нет Ответов