Вкратце

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

Интерфейс — это абстрактный класс, у которого ни один метод не реализован, все они публичные и нет переменных класса.

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

Абстрактный класс нужен, когда нужно семейство классов, у которых есть много общего. Конечно, можно применить и интерфейс, но тогда нужно будет писать много идентичного кода.

(звезда) В некоторых языках (С++) специального ключевого слова для обозначения интерфейсов нет.

Можно считать, что любой интерфейс — это уже абстрактный класс, но не наоборот.

Отличия абстрактного класса от интерфейса в 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)

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

(warning) Нельзя инициализировать объект абстрактного класса — это отличие от использования обычного класса для наследования.

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


Источники:

(1) https://ru.stackoverflow.com/questions/235352/%D0%9E%D1%82%D0%BB%D0%B8%D1%87%D0%B8%D1%8F-%D0%B0%D0%B1%D1%81%D1%82%D1%80%D0%B0%D0%BA%D1%82%D0%BD%D0%BE%D0%B3%D0%BE-%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%B0-%D0%BE%D1%82-%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81%D0%B0-abstract-class-and-interface

(2) https://qna.habr.com/q/10682

(3) Г.Шилдт, Полное руководство C#)

(4) https://www.scorp13.com/workflow/raznica-mezhdu-abstraktnym-klassom-i-interfeysom-v-php.html

Tags

Нет комментариев

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.