Чем интерфейс отличается от абстрактного класса java
Перейти к содержимому

Чем интерфейс отличается от абстрактного класса java

  • автор:

Сравнение абстрактных классов и интерфейсов в Java

В мире программирования на Java, мы часто сталкиваемся с понятиями абстрактных классов и интерфейсов. Но что это такое и в чем ключевые различия между этими двумя концепциями? �� Давайте разберемся!

Абстрактные классы в Java

Абстрактный класс — это класс, который содержит один или несколько абстрактных методов. Абстрактный метод — это метод, который объявлен, но не имеет реализации. Абстрактные классы не могут быть инстанцированы, они служат основой для подклассов.

Например, мы можем создать абстрактный класс «Животное» с абстрактным методом «издать звук». Подклассы «Собака» и «Кошка» будут иметь разные реализации этого метода.

abstract class Animal < abstract void makeSound(); >class Dog extends Animal < void makeSound() < System.out.println("woof"); >> class Cat extends Animal < void makeSound() < System.out.println("meow"); >>

Для более подробного изучения абстрактных классов рекомендуется прочесть статью Что такое абстрактные классы в Java и чем они отличаются от интерфейсов. А если вам интересно, могут ли абстрактные классы иметь конструкторы, обратите внимание на эту статью Могут ли абстрактные классы иметь конструкторы в Java?.

Интерфейсы в Java

Интерфейс в Java — это полностью абстрактный класс, который может содержать только абстрактные методы и поля. Интерфейс представляет собой декларацию методов, которые должны быть реализованы в классе, который его реализует.

interface Animal < void makeSound(); >class Dog implements Animal < public void makeSound() < System.out.println("woof"); >> class Cat implements Animal < public void makeSound() < System.out.println("meow"); >>

Подробнее о интерфейсах и использовании методов по умолчанию можно прочитать в статье Использование методов по умолчанию в интерфейсах Java 8+ и абстрактных методов.

Сравнение абстрактных классов и интерфейсов

Существуют ключевые различия между абстрактными классами и интерфейсами в Java:

  1. Множественная реализация: Класс может реализовать несколько интерфейсов, но может наследоваться только от одного абстрактного класса.
  2. Определение методов: Интерфейсы могут содержать только объявления методов, а абстрактные классы могут содержать и объявления, и реализации методов.
  3. Конструкторы и поля: Абстрактные классы могут иметь конструкторы и поля, в то время как интерфейсы не могут.

Заключение

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

Чем интерфейс отличается от абстрактного класса java

Говорили, что будет понятно, почему InputStream и OutputStream — это по сути интерфейсы, но все-же абстрактные классы. Обманули?

Alex Уровень 27
2 января 2024
И каждый раз, когда я уходил от тебя, ты снова возвращалась ��
Максим Li Уровень 36
12 ноября 2023
ElenaN Уровень 37
28 октября 2023

Вроде статья начиналась как статья про абстрактные классы и интерфейсы, а потом вдруг — а, кстати, помните пару уровней назад вы ничего не поняли про I/O? вот, держите!

Василь Уровень 27
25 октября 2023
мені одному здалося що стаття більше про ріадери, а не про абстрактні класи та інтерфейси?
Александра 😉 Уровень 32
6 сентября 2023

Всем привет!! Изучая Java, в очередной раз осознала нехватку живого общения с единомышленниками =). Вот и решила создать группу в телеграмм, где Java — студенты смогут не только обсуждать вопросы по изучению Java, но и организовывать живые встречи. Кому интересно, вступайте =) https://t.me/JavaCommunityMoscow

Dmitry Vidonov Уровень 29 Expert
4 сентября 2023
Молодец Aditi! Продуктивная бабца!
chess.rekrut Уровень 25
22 августа 2023
Rustam Уровень 35 Student
31 июля 2023
начал понимать суть интерфейсов, спасибо
Сообщество

JavaRush — это интерактивный онлайн-курс по изучению Java-программирования c нуля. Он содержит 1200 практических задач с проверкой решения в один клик, необходимый минимум теории по основам Java и мотивирующие фишки, которые помогут пройти курс до конца: игры, опросы, интересные проекты и статьи об эффективном обучении и карьере Java‑девелопера.

Подписывайтесь
Язык интерфейса
«Программистами не рождаются» © 2024 JavaRush
Скачивайте наши приложения
«Программистами не рождаются» © 2024 JavaRush

Этот веб-сайт использует данные cookie, чтобы настроить персонально под вас работу сервиса. Используя веб-сайт, вы даете согласие на применение данных cookie. Больше подробностей — в нашем Пользовательском соглашении.

Чем интерфейс отличается от абстрактного класса java

Абстрактные классы vs интерфейсы в Java
Различия между абстрактными классами и интерфейсами в Java

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

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

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

Например, до появления Java 8, при возникновении вопроса на собеседовании типа: «Назовите разницу между абстрактным классом и интерфейсом», вы смело могли сказать, что интерфейс представляет собой контракт, содержащий методы без реализации, которые должны быть реализованы в классах, имплементирующих этот интерфейс. А абстрактный класс — это класс, который содержит (или не содержит) абстрактные методы и общий для его потомков код.

Также раньше вы могли сказать, что интерфейс не может содержать статические, приватные или методы по умолчанию, и что в нем вообще не может быть реализовано никакой логики. В техническом плане все ограничения остались в прошлом — граница между этими понятиями сейчас уже почти стерта. Но с фундаментальной точки зрения ничего не изменилось!

В данной статье будут рассмотрены как фундаментальные, так и технические различия между интерфейсом и абстрактным классом.

1. Фундаментальное отличие

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

Например, такое поведение как «движение» может быть применимо к разным типам объектов: машина, кот, котировки курса и т. д. Эти объекты не имеют ничего общего, кроме того, что они могут двигаться.

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

Если перенести это поведение в код, написанный на языке Java, то получится следующее:

 interface Movable

Абстрактный же класс описывает некий абстрактный объект (автомобиль, человека, кота и т. д.), а не только поведение.

Если мы рассуждаем про абстрактный «автомобиль», то в нашей голове сразу формируется картинка с объектом. Мы сразу понимаем, что автомобиль содержит двигатель, колеса и может двигаться, поворачивать, ускоряться или тормозить. Он также будет иметь поля для хранения внутренних деталей, таких как мотор, колеса и тормоза. Вы получите все это просто сказав слово «автомобиль».

При этом кот и котировка курса валют не могут быть автомобилем, даже если они также могут двигаться.
На основе вышесказанного создадим класс Automobile:

 abstract class Automobile

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

А теперь поговорим про различия в технической реализации.
2. Технические отличия

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

2.1. Синтаксис создания

Итак, при создании абстрактного класса указывается ключевое слово abstract, а при определении интерфейса — interface.

Пример абстрактного класса:

 public abstract class MyAbstractClass < // поля и конструкторы // абстрактные методы // методы с реализацией >

Пример интерфейса:

 public interface MyInterface < // объявление констант // методы без реализации // статические методы // методы по умолчанию (default) // приватные методы >

2.2 Синтаксис использования

При наследовании от абстрактного класса используется ключевое слово extends (с англ. «расширяет»), а при реализации интерфейса — implements (с англ. «реализует»).

В приведенном ниже коде класс MyClass расширяет MyAbstractClass:

 public class MyClass extends MyAbstractClass < // реализация абстрактных методов // иной код >

А тут класс MyClass реализует интерфейс MyInterface:

 public class MyClass implements MyInterface < // реализация методов интерфейса // иной код >

Класс может одновременно и наследоваться от абстрактного класса (только одного) и реализовать один или множество интерфейсов.

Например, класс MyClass реализует интерфейс MyInterface, MyInterface_2 и MyInterface_3:

 class MyClass extends MyAbstractClass implements MyInterface, MyInterface_2, MyInterface_3 < // реализация абстрактных методов абстрактного класса // реализация методов из интерфейсов // иной код >

2.3 Наличие конструктора

Как вы знаете, невозможно создать экземпляр абстрактного класса. Но, объявить и определить в нем конструктор мы можем. В противном случае за нас это сделает компилятор, создав конструктор по умолчанию. Без него код просто не скомпилируется, поскольку при создании конкретного класса первым оператором будет неявный вызов super() конструктора суперкласса, в данном случае абстрактного.

Добавим в абстрактный класс MyAbstractClass конструктор:

 public abstract class MyAbstractClass < public MyAbstractClass() < System.out.println("Конструктор из MyAbstractClass"); >> 

Также добавим конструктор в MyClass:

 public class MyClass extends MyAbstractClass < public MyClass() < System.out.println("Конструктор из MyClass"); >> 

В классе Main создадим объект и запустим программу:

 public class Main < public static void main(String[] args) < MyAbstractClass myObject = new MyClass(); >> 

Результат выполнения программы:

Для интерфейсов понятия «конструктор» не существует.
2.4 Типы переменных

Все переменные в интерфейсах неявно являются public static final (т.е. константами). «final» подразумевает, что переменной обязательно должно быть присвоено значение во время инициализации.

Рассмотрим следующий код:

 public interface MyInterface < // эта строка не скомпилируется int value_1; int value_2 = 1; public final int value_3 = 1; static int value_4 = 1; public final static int value_5 = 1; static final int value_6 = 1; >

Поскольку value _1 не присвоено конкретное значение, а она является неявно final, код с такой строкой не скомпилируется. Остальные строки не вызовут ошибок, т.к. public static final можно не указывать (если указать, то IDE выделит их серым цветом, подчеркивая «избыточность»).

В абстрактных классах переменные могут быть любыми — абстрактность класса не накладывает ограничений.

Например, следующий код является корректным:

 public abstract class MyAbstractClass

2.5 Модификаторы доступа методов

Модификаторы доступа для абстрактных классов могут быть любыми. При этом, все методы, кроме абстрактных, должны иметь реализацию.

А вот в случае с интерфейсами модификаторы доступа могут быть только двух типов, public и private (последний — начиная с Java 9).

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

Рассмотрим следующий код:

 public interface MyInterface_2 < void publicAbstractMethod_1(); public void publicAbstractMethod_2(); void publicAbstractMethod_3(); private void privateMethod() < // Реализация метода >> 

Методы publicAbstractMethod_1 и publicAbstractMethod_3 являются неявно public.
2.6 Методы с реализацией
Для абстрактного класса все методы, кроме абстрактных, должны иметь реализацию.

Для интерфейсов, начиная с Java 8, вводится понятие метода по умолчанию. Такие методы, во-первых, должны иметь реализацию в интерфейсе, а во-вторых, помечены ключевым словом default. Они также являются неявно public. При этом они не должны в обязательном порядке иметь реализацию в реализующем интерфейс классе, но могут быть в нем переопределены.

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

Например, код ниже скомпилируется:

 public interface MyInterface_3 < default void defaultMethod() < // Реализация метода >public default void defaultMethod_2() < // Реализация метода >private static void privateStaticMethod() < // Реализация метода >public static void publicStaticMethod_1() < // Реализация метода >static void publicStaticMethod_2() < // Реализация метода >> 

2.7 Наследование

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

Абстрактный класс может наследовать как обычный класс, так и абстрактный. В обоих случаях это будет только один класс (в Java нет множественного наследования классов).

В то же время абстрактный класс также может реализовать до 65 535 интерфейсов (это связано с ограничением константы interfaces_count в структуре ClassFile).

В этом месте давайте немного отойдем от темы сравнения и затронем множественное наследование. В некоторых источниках однозначно указывается, что множественного наследования в Java нет. В других источниках говорится, что множественного наследования как бы нет, но оно реализуется через интерфейсы.

  • наследование состояния (Inheritance of State)
  • наследование реализации (Inheritance of Implementation)
  • наследование типа (Inheritance of Type)

Java не поддерживает множественное наследование состояния, но поддерживает множественное наследование реализации (как вариант, на основе методов по умолчанию от интерфейсов). Она также поддерживает множественное наследование типов (поскольку может реализовать более одного интерфейса).

Именно таким должен быть ответ на вопрос о множественном наследовании в Java.
3. Рекомендации к применению абстрактных классов и интерфейсов
В соответствии с рекомендациями Oracle абстрактный класс нужно использовать в следующих случаях:

  • Необходимо выделить общий код между несколькими тесно связанными классами
    Пояснение: это типовой рефакторинг, целью которого является устранение дублирования кода.
  • Мы ожидаем, что классы, расширяющие абстрактный класс, имеют много общих методов, полей или требуют модификаторов доступа, отличных от public (protected и private)
    Пояснение: ранее мы писали, что в интерфейсах методы, имеющие реализацию (помеченные ключевым словом default), являются неявно public. Если же метод, имеющий реализацию, помечен явно как private, то он не сможет быть использован в классах, реализующих этот интерфейс, а только в других методах интерфейса. Поэтому, если нам нужны методы с модификаторами доступа не public, мы должны использовать абстрактный класс.
  • Мы хотим объявить не static или не final поля для изменения состояния объекта.
    Пояснение: ранее мы писали, что все переменные в интерфейсах неявно являются public static final — из-за чего они не могут быть изменены.

Для использования интерфейсов существуют следующие причины:

  • Планируется, что несвязанные между собой классы будут реализовывать интерфейс. Например, интерфейсы Comparable и Cloneable реализуются многими несвязанными между собой классами.
    Пояснение: как мы выяснили ранее, концептуальное назначение интерфейса — описание «поведения», а не «состояния» (в отличие от абстрактного класса). Соответственно, реализовать это поведение могут любые классы, несвязанные между собой, которые просто должны что-то «уметь» делать или «как-то» себя вести.
  • Требуется детализировать или определить поведение определенного типа данных, но при этом мы не хотим беспокоиться о том, кто реализует его поведение.
    Пояснение: пояснение к прошлому пункту также актуально и для этого — нам все равно, какие классы будут реализовывать наш интерфейс и в каких пакетах находятся. Мы просто хотим, чтобы они вели себя в соответствии с «нашим контрактом», прописанным в интерфейсе в виде методов без реализации.
  • Мы хотим воспользоваться преимуществами множественного наследования типов

Приведем наглядный пример выбора между абстрактным классом и интерфейсом.

Существует паттерн «Шаблонный метод», определение которого звучит так: «шаблонный метод определяет основу алгоритма и позволяет подклассам переопределить некоторые его шаги, не изменяя структуру, в целом».

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

Так вот вопрос, а что нам мешает разместить абстрактные и шаблонные методы в интерфейсе? В качестве шаблонного метода мы могли бы использовать метод по умолчанию. Вроде звучит логично, согласитесь?

Но обратите еще раз внимание на определение шаблонного метода. Там есть такие слова: «… не изменяя структуру, в целом». Подклассы абстрактного класса не должны иметь возможность переопределить шаблонный метод с целью изменения логики (алгоритма) его работы. По этой причине шаблонные методы объявляются как final и не могут использовать интерфейсы с их методами по умолчанию (могут быть переопределены) вместо абстрактных классов. Вся идея паттерна в этом случае будет нарушена.

Для того чтобы рассмотреть разницу между интерфейсом и абстрактным классом немного глубже, рекомендуется обратиться к книге «Java. Эффективное программирование», Блох Д., 3-е издание.

В разделе 4.6 этой книги говорится о следующих причинах предпочтения интерфейсов абстрактным классам:

1. Существующие классы можно легко приспособить для реализации но­вого интерфейса.
Пояснение: для этого достаточно написать implements и реализовать необходимые методы. Но уже имеющиеся классы в общем случае не могут быть переделаны для расширения нового абстрактного класса. Если вы хотите, чтобы два класса расширяли один и тот же абстрактный класс, вам придется поднять этот класс в иерархии настолько высоко, чтобы он стал предком обоих этих классов. Это может привести к нарушению логики иерархии типов, заставляя всех потомков нового абстрактного класса расширять его независимо от того, насколько это целесообразно.

2. Интерфейсы идеально подходят для создания миксинов.
Пояснение: Миксин (mixin) — это тип, который класс может реализовать в дополнение к своему «первичному типу», объявляя о том, что этот класс предоставляет некоторое необязательное поведение. Например, Comparable является таким интерфейсом-миксином, т. к. добавляет (примешивает) к первоначальным возможностям типа дополнительную функциональность.
Использовать абстракт­ные классы для создания миксинов нельзя по той же причине, по которой их невозможно приспособить к уже имеющимся классам: класс не может иметь больше одного родителя, и в иерархии классов нет подходящего места, куда можно поместить миксин.

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

4. Интерфейсы обеспечивают безопасное и мощное развитие функци­ональности с использованием шаблона «Декоратор». Паттерн «Декоратор» позволяет динамически (в ходе выполнения программы) добавлять объекту новые возможности (состояние и/или поведение) на основе композиции.

Абстрактные классы в Java и их отличия от интерфейсов: кратко и без воды

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

Иллюстрация: Dana Moskvina / Skillbox Media

Паша Лебедев

Паша Лебедев
Пишет на Java. Верит в Agile. Пьёт много кофе и не любит грязный код.

Абстрактный класс — это класс, который содержит методы без реализации. Но зачем он такой нужен? Давайте разбираться.

Представим, что нам нужно описать несколько животных — и у каждого будет свой класс. Мы соберём их характеристики, опишем в полях и методах. У некоторых животных характеристики будут совпадать — например, и у гепарда, и у коня 4 ноги. А у некоторых — не совпадут: кролик ест траву, а тигр — других животных.

Однако, несмотря на несовпадение, мы можем выделить шаблонные характеристики: количество лап, издаваемый звук, приём пищи, передвижение. Эти шаблонные характеристики мы можем собрать в одном месте — абстрактном классе «Животное» и указать компилятору, что наполним их конкретными данными и поведением позже — в классах отдельных животных или групп животных.

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

При этом абстрактным объект класса «Животное» создать нельзя — ведь в природе «просто животного» не существует, есть только волки, лисы, бегемоты и прочие слоны.

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

Давайте рассмотрим пример абстрактного класса в Java.

public abstract class Animal < Integer countOfLegs; Double weight; String color; public abstract void run( ); public void eat( ) < System.out.println("Animal says nyam-nyam"); > >

Как вы видите, абстрактный класс очень похож на обычный класс. Чтобы сделать класс абстрактным, нам нужно добавить ключевое слово abstract в описание класса и в методы, которые мы хотим оставить абстрактными, — то есть определить уже в конкретных классах (медведь, лиса, лягушка).

В абстрактном классе мы можем описать некоторые поля, которые будут отражать определённые свойства объекта или добавить обычный метод с реализацией по умолчанию.

Именно так мы и сделали в примере выше: добавили переменные для веса, цвета и количества ног у животного, а также описали два метода: run («бежать») и eat («кушать»). В нашем случае метод run — абстрактный, а у метода eat есть реализация по умолчанию. Это значит, что в классах, которые наследуют от Animal, мы обязаны добавить определение метода run, а переопределять или нет метод eat, зависит от наших задач и желания.

Теперь давайте попробуем создать класс на основе абстрактного класса. Пусть это будет класс, описывающий собаку.

public class Dog extends Animal < @Override public void run() < System.out.println("Dog says gaf-gaf"); > >

Здесь extends Animal означает, что мы наследуем класс Animal. Как только мы создадим пустой класс Dog, компилятор сразу подсветит его красным и выведет такое сообщение:

Error: (3, 8) java: com.company.Dog is not abstract and does not override abstract method run () in com.company.Animal

Это значит, что мы обязаны переопределить метод run() — что мы и сделали с помощью аннотации @Override.

Теперь давайте создадим объект класса Dog. Как мы видим, после его создания нам доступны все переменные и методы из класса Animal. Попробуем вызвать eat и run.

public static void main(String[] args) < Dog scooby = new Dog(); scooby.eat(); scooby.run(); >

Вот что мы увидим в консоли:

Animal says nyam-nyam

Dog says gaf-gaf

Итак, давайте выделим важные моменты:

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

Больше рецептов на Java — в нашей базе знаний.

Отличия абстрактного класса и интерфейса

На собеседованиях часто задают вопрос, чем отличаются абстрактные классы и интерфейсы. Вот их основные отличия:

  • Интерфейсы описывают только часть функциональности объекта — определённые признаки. Абстрактный класс же может описывать целую категорию разных объектов, а его характеристики имеют право наследовать только те объекты, которые являются частью этой категории. Например, собаки и волки — часть общей категории «Животные», а интерфейс, описывающий умение бегать, может реализовать и человек, и робот, и собака.
  • Интерфейс описывает только поведение (методы), и у него нет полей. Точнее, есть возможность их объявить, но они будут public static final. В то же время абстрактный класс может содержать классические поля, которые будут принадлежать разным объектам.
  • Наследник абстрактного класса обязан наследовать все его составляющие, а интерфейс создан только для реализации (имплементирования). Поэтому в Java мы можем наследовать класс только от одного класса, а на реализацию интерфейсов внутри одного класса ограничений нет.

Когда использовать абстрактный класс, а когда — интерфейс

Интерфейсы и абстрактные классы — это разные инструменты, разработанные для разных целей, хотя у них и есть общие черты.

Когда лучше использовать абстрактные классы:

  • Вы хотите избежать дублирования кода, реализуя несколько тесно связанных классов из одной семантической категории.
  • Классы, которые будут расширять ваш абстрактный класс, имеют много общих свойств и будут реализовывать много похожих методов.
  • Наследуемый класс используется в отношении IS-A — то есть класс-наследник только расширяет функциональность абстрактного класса.
  • Проект уже частично написан, а вы знаете, что выбранные классы будут часто меняться и дополняться новыми методами и полями. То есть поддерживать абстрактный класс и дополнять его намного проще, чем проектировать интерфейс и добавлять его новые методы во все места в коде, где они должны реализовываться.

Когда лучше использовать интерфейсы:

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

Это лишь базовые и самые распространённые ситуации. Решая конкретные задачи, лучше советоваться с более опытными разработчиками или принимать самостоятельное решение.

Заключение

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

Читайте также:

  • Что такое класс в Java
  • Как разработчик на C++ превратил свой пет-проект в прибыльный стартап
  • Основные принципы ООП: большой гайд по объектно-ориентированному программированию

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

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