в чем разница между абстрактным классом и интерфейсом
Разница между абстрактным классом и интерфейсом в Java
Разница между абстрактным классом и интерфейсом в Java. Разница между интерфейсом и абстрактным классом. Интерфейс или абстрактный класс, Java 8 изменяет эффект
Разница между абстрактным классом и интерфейсом-один из популярных вопросов для интервью. Абстрактный класс и интерфейс являются основной частью языка программирования Java. Выбор интерфейса или абстрактного класса – это дизайнерское решение, с которым сталкивается каждый архитектор.
В этом посте мы узнаем о разнице между абстрактным классом и интерфейсом и о том, когда следует использовать интерфейс поверх абстрактного класса и наоборот.
Разница между абстрактным классом и интерфейсом
Интерфейс или Абстрактный класс
Выбор между интерфейсом или абстрактным классом для предоставления контракта для подклассов является дизайнерским решением и зависит от многих факторов. Давайте посмотрим, когда интерфейсы являются лучшим выбором и когда мы можем использовать абстрактные классы.
Используйте абстрактные классы и интерфейс как
Мы всегда должны начинать с базового интерфейса и определять методы, которые должен реализовывать каждый подкласс, а затем, если есть некоторые методы, которые должен реализовывать только определенный подкласс, мы можем расширить базовый интерфейс и создать новый интерфейс с помощью этих методов.
Подклассы будут иметь возможность выбирать между базовым интерфейсом или дочерним интерфейсом для реализации в соответствии с его требованиями.
Если количество методов значительно увеличивается, неплохо было бы предоставить скелетный абстрактный класс, реализующий дочерний интерфейс и предоставляющий подклассам гибкость при выборе между интерфейсом и абстрактным классом.
Изменения интерфейса Java 8
Начиная с Java 8 и далее, у нас могут быть реализации методов в интерфейсах. Мы можем создавать как стандартные, так и статические методы в интерфейсах и предоставлять для них реализацию.
Это позволило преодолеть разрыв между абстрактными классами и интерфейсами, и новые интерфейсы-это правильный путь, потому что мы можем расширить его еще больше, предоставив реализации по умолчанию для новых методов.
ООП. Часть 6. Абстрактные классы и интерфейсы
Узнайте истинную мощь наследования и полиморфизма! Раскрываем секреты абстрактных классов и интерфейсов.
В предыдущей статье мы увидели, насколько удобнее становится ООП благодаря наследованию. Но оно может стать ещё лучше, если использовать абстрактные классы и интерфейсы.
Все статьи про ООП
Пишет о программировании, в свободное время создает игры. Мечтает открыть свою студию и выпускать ламповые RPG.
Абстрактные классы
Особенность абстрактных классов в том, что их можно использовать только как родительский класс, то есть вы не можете создать объект. Для их объявления используется ключевое слово abstract.
Это может понадобиться, чтобы объединить реализацию других схожих классов. Например, в вашей игре должны быть персонаж игрока и NPC (неигровые персонажи). У них могут быть общие свойства (имя, координаты) и методы (перемещение, изменение анимации).
Чтобы не повторять код несколько раз, можно вынести реализацию этих свойств и методов в абстрактный класс Character:
Тут всё как у обычных классов, но в конце можно заметить объявление свойства и метода без реализации. Реализация этих абстрактных свойств должна находиться в дочернем классе:
Когда объявляется реализация такого члена класса, необходимо указать ключевое слово override. Абстрактными могут быть следующие члены класса:
Дочерний класс должен реализовывать все члены родительского абстрактного класса, кроме тех случаев, когда дочерний класс тоже абстрактный.
В остальном всё очень похоже на обычные классы. Например, поле Y класса Character публичное, чтобы можно было использовать его в свойстве Y дочерних классов.
Абстрактный класс должен быть публичным.
Разница между абстрактным классом и интерфейсом в Java
Некоторые из популярных вопросов интервью: «В чем разница между абстрактным классом и интерфейсом», «Когда вы будете использовать абстрактный класс и когда вы будете использовать интерфейс». Итак, в этой статье мы пройдем эту тему.
Прежде чем перейти к различиям между ними, давайте рассмотрим их введение.
Абстрактный класс
Абстрактные классы создаются для захвата общих характеристик подклассов. Его нельзя создать, его подклассы можно использовать только как суперкласс. Абстрактные классы используются для создания шаблона для его подклассов вниз по иерархии.
Давайте возьмем пример класса JDK GenericServlet:
Когда HttpServlet расширяет универсальный сервлет, он обеспечивает реализацию метода service ():
Интерфейс
Интерфейс — это коллекция абстрактных методов. Класс реализует интерфейс, тем самым наследуя абстрактные методы интерфейса. Так что это своего рода подписание контракта, вы соглашаетесь, что если вы реализуете этот интерфейс, то вам придется использовать его методы. Это просто шаблон, он ничего не может сделать сам.
Давайте возьмем пример внешнего интерфейса:
Когда вы реализуете этот интерфейс, вы должны реализовать два вышеупомянутых метода:
Абстрактный класс против интерфейса
параметр | Абстрактный класс | Интерфейс |
Реализация метода по умолчанию | Может иметь реализацию метода по умолчанию | Интерфейсы — это чистая абстракция. Не может быть реализации вообще. |
Реализация | Подклассы используют ключевое слово extends для расширения абстрактного класса, и они должны обеспечивать реализацию всех объявленных методов в абстрактном классе, если только подкласс не является также абстрактным классом. | подклассы используют ключевое слово Implements для реализации интерфейсов и должны обеспечивать реализацию для всех методов, объявленных в интерфейсе. |
Конструктор | Абстрактный класс может иметь конструктор | Интерфейс не может иметь конструктор |
Отличается от обычного Java-класса | Абстрактные классы почти такие же, как классы Java, за исключением того, что вы не можете создать их экземпляр. | Интерфейсы совсем другого типа |
Модификатор доступа | Методы абстрактного класса могут иметь публичный, защищенный, приватный и модификатор по умолчанию | Методы интерфейса по умолчанию общедоступны. вы не можете использовать любой другой модификатор доступа с ним |
Основной () метод | Абстрактные классы могут иметь метод main, поэтому мы можем его запустить | Интерфейс не имеет основного метода, поэтому мы не можем его запустить. |
Множественное наследование | Абстрактный класс может расширять еще один класс и может реализовывать один или несколько интерфейсов. | Интерфейс может распространяться только на один или несколько интерфейсов. |
скорость | Это быстрее, чем интерфейс | Интерфейс несколько медленнее, так как поиск метода в классе занимает некоторое время |
Добавление нового метода | Если вы добавляете новый метод в абстрактный класс, вы можете обеспечить его реализацию по умолчанию. Таким образом, вам не нужно менять свой текущий код | Если вы добавляете новый метод в интерфейс, вы должны изменить классы, которые реализуют этот интерфейс |
Когда использовать Абстрактный класс и интерфейс:
Введение стандартных и статических методов в Java 8
Oracle попытался преодолеть разрыв между абстрактным классом и интерфейсом, введя в интерфейс концепцию стандартных и статических методов. Так что теперь мы можем обеспечить реализацию метода по умолчанию в интерфейсе и не будем применять класс для его реализации. Я расскажу об этой теме в моем следующем посте.
В чем разница между абстрактным классом и интерфейсом
1. Существующие классы можно легко приспособить для реализации нового интерфейса.
Пояснение: для этого достаточно написать implements и реализовать необходимые методы. Но уже имеющиеся классы в общем случае не могут быть переделаны для расширения нового абстрактного класса. Если вы хотите, чтобы два класса расширяли один и тот же абстрактный класс, вам придется поднять этот класс в иерархии настолько высоко, чтобы он стал предком обоих этих классов. Это может привести к нарушению логики иерархии типов, заставляя всех потомков нового абстрактного класса расширять его независимо от того, насколько это целесообразно.
2. Интерфейсы идеально подходят для создания миксинов.
Пояснение: Миксин (mixin) — это тип, который класс может реализовать в дополнение к своему «первичному типу», объявляя о том, что этот класс предоставляет некоторое необязательное поведение. Например, Comparable является таким интерфейсом-миксином, т.к. добавляет (примешивает) к первоначальным возможностям типа дополнительную функциональность.
Использовать абстрактные классы для создания миксинов нельзя по той же причине, по которой их невозможно приспособить к уже имеющимся классам: класс не может иметь больше одного родителя, и в иерархии классов нет подходящего места, куда можно поместить миксин.
3. Интерфейсы позволяют создавать неиерархические каркасы типов.
Пояснение: иерархии типов прекрасно подходят для организации некоторых сущностей, но зато сущности других типов невозможно аккуратно уложить в строгую иерархию. Альтернативой им является раздутая иерархия классов.
4. Интерфейсы обеспечивают безопасное и мощное развитие функциональности с использованием шаблона Декоратор. Паттерн Декоратор позволяет динамически (в ходе выполнения программы) добавлять объекту новые возможности (состояние и/или поведение) на основе композиции.
Отличия абстрактного класса от интерфейса (abstract class and interface)
Каковы отличия между абстрактным классом и интерфейсом?
13 ответов 13
Абстрактный класс — это класс, у которого не реализован один или больше методов (некоторые языки требуют такие методы помечать специальными ключевыми словами).
Интерфейс — это абстрактный класс, у которого ни один метод не реализован, все они публичные и нет переменных класса.
Интерфейс нужен обычно когда описывается только интерфейс (тавтология). Например, один класс хочет дать другому возможность доступа к некоторым своим методам, но не хочет себя «раскрывать». Поэтому он просто реализует интерфейс.
Абстрактный класс нужен, когда нужно семейство классов, у которых есть много общего. Конечно, можно применить и интерфейс, но тогда нужно будет писать много идентичного кода.
В некоторых языках (С++) специального ключевого слова для обозначения интерфейсов нет.
Можно считать, что любой интерфейс — это уже абстрактный класс, но не наоборот.
tl;dr: Абстрактный класс — средство разработки классов на нижнем уровне, средство для повторного использования кода; интерфейс — средство выражения семантики класса. Таким образом, это совершенно разные, мало связанные между собой понятия.
Думайте об этом по-другому.
Абстрактный класс — это «заготовка» класса: реализовано большинство методов (включая внутренние), кроме нескольких. Эти несколько нереализованных методов вполне могут быть внутренними методами класса, они лишь уточняют детали имплементации. Абстрактный класс — средство для повторного использования кода, средство, чтобы указать, какой метод обязан быть перекрыт для завершения написания класса.
Интерфейс же — это своего рода контракт: интерфейсы используются в определениях чтобы указать, что объект, который будет использован на самом деле, должен реализовывать (для входных параметров) или будет гарантированно реализовывать (для выходных параметров) набор методов и (что намного важнее!) иметь определённую семантику. Интерфейс вполне может быть и пустым, тем не менее, имплементировать интерфейс означает поддерживать данную семантику.
Абстрактные классы идеологически схожи с шаблонами C++: и те, и другие являются заготовками классов, но шаблону для получения класса нужно специфицировать шаблонные типы, а абстрактному классу — абстрактные методы.
Интерфейсы идеологически схожи с заголовочными файлами C++: они раскрывают методы и скрывают конкретную реализацию.
Вопрос о том, является ли интерфейс или абстрактный класс собственно классом — техническая подробность реализации, зависящая от конкретного языка программирования. Например, в C++ интерфейсы отсутствуют вовсе, и их приходится эмулировать классами без данных. Абстрактный класс в C++ как таковой также отсутствует, но им можно считать любой класс с абстрактными методами. (Отсюда ограничение C++: как минимум 1 абстрактный метод в абстрактном классе.) Также в C++ можно (непрямо) инстанциировать абстрактный класс, вызвать абстрактный метод и (возможно) получить ошибку времени выполнения. В C# интерфейсы и абстрактные классы встроены в язык.
Пример (на C#, конкретный язык значения не имеет):
Мне кажется достаточно любопытным, что данный вопрос помечен тегом «ооп», но при этом во многих ответах явно просачиваются специфические аспекты конкретных языков программирования. Я же постараюсь дать ответ исходя из понятий ООП и лишь потом показать, почему вообще это различие появилось в некоторых языках программирования.
Абстрактные классы и интерфейсы имеют определенное отношение к наследованию, точнее к моделированию мира. С их помощью мы хотим выразить, что у определенной группы вещей в нашей системе есть что-то общее: некоторое общее поведение, которое отличает эту группу штуковин от всех остальных.
Допустим, для примера, мы хотим смоделировать кнопки в интерфейсе пользователя. Поскольку мы говорим об ООП, то мы выделим некоторый тип Кнопки с некоторым набором операций (которые определяют поведение) и скрытого состояния, на которое опирается поведение (да, скрытого состояния может и не быть). При этом мы можем выделить три вида операции:
Конкретная фиксированная операция, которая должна быть абсолютно стабильно для всех типов кнопок.
Конкретная операция с поведением по умолчанию (т.е. операция, чье поведение подходит для многих типов кнопок, но могут быть кнопки с другим поведением).
Декларация операции без конкретной реализации (т.е. операция, чье поведение определить невозможно, поскольку на этом этапе не известно разумное поведение по умолчанию или же операции могут слишком сильно различаться у разных кнопок).
Другими словами, тип Кнопки может содержать невиртуальные методы (non-virtual methods), виртуальные методы (virtual methods) и абстрактные методы (abstract methods).
Наличие разных типов методов является очень важным инструментом моделирования и позволяет весьма точно выражать намерения проектировщика. Например, мы можем добавить невиртуальную операцию «Нажатия на кнопку», которая будет делегировать часть своей работы виртуальному (или абстрактному методу) «Обработать нажатие», но при этом всегда выполнять определенную часть работы (прозорливый читатель увидит в этом описании паттерн «Шаблонный метод»).
После того, как мы определили базовый тип, пришло время определить произвольные типы. И тут начинаются вопросы. Точнее, вопросов никаких не возникает, когда у типа есть лишь один непосредственный базовый тип или все базовые типы содержат лишь декларации операций. Не проблема, унаследовать «Кнопку меню» от «Кнопки» и переопределить метод «Нажать на кнопку». Но что, если наш тип «Кнопка меню» будет отнаследован от двух типов с одной и той же виртуальной операцией? Как переопределить лишь одну, а оставить другую? А как быть клиенту нового типа и различить, какую операцию вызвать? А что если у двух базовых типов есть поле с одним именем? А что если у одного базового типа метод «Нажать кнопку» реализован, а у другого – лишь описан в виде декларации?
Нет, все эти проблемы решаемы, и в С++, и Eiffel, и других языках программирования вы можете довольно гибко контролировать, что и как переопределять, что прятать, что выставлять наружу и как вызвать метод определенного базового типа. Но для авторов некоторых языков программирования подобная сложность показалась излишней, и они пошли на хитрость и отделили типы, которые содержат лишь декларации методов в отдельную категорию, и так появились интерфейсы.
Теперь будет легко провести разницу между тремя понятиями – интферфейса, абстрактного базового класса и конкретного базового класса.
Интерфейс – описывает некоторое семейство типов и содержит лишь декларации операций (да, я осознанно пишу слово «декларация», а не использую слово «контракт», которое в ООП имеет вполне определенное значение).
Абстрактный базовый класс описывает некоторое семейство типов, но помимо декларации операций может содержать реализации по умолчанию (виртуальные методы) и фиксированные операции (невиртуальные методы).
Конкретный класс описывает некоторое семейство типов, которое готово для использования клиентами. Такой класс не может содержать декларации операций и все его операции должны быть либо фиксированными (невиртуальные методы) или содержать реализацию по умолчанию (виртуальные методы). Есть еще один подвид конкретных классов – запечатанный (sealed) класс – это разновидность конкретного класса отнаследоваться от которого невозможно, а значит он может содержать лишь конкретные операции.
Выделение интерфейсов в отдельную категорию полезно не только с точки зрения упрощения реализации языков программирования, но и для выделения разных подходов к моделированию. Так, например, наследование классов моделирует отношение «Является» («Кнопка меню» ЯВЛЯЕТСЯ «Кнопкой»), а базовые классы обычно содержат определенный функционал, тесно связанный с функционалом производного класса. Базовые классы не просто моделируют группу типов, но и позволяют использовать повторно существующий функционал.
Интерфейсы же, по своей природе обладают меньшей связностью (low coupling), поскольку не обладают конкретным поведением, которое может осложнить жизнь класса-наследника. Интерфейсы также могут моделировать отношение «Является» («Кнопка меню» ЯВЛЯЕТСЯ «IКнопкой»), но могут определять и менее жесткое отношение «Может выполнять роль» (CAN DO). Например, интерфейс IEquatable из BCL определяет «дополнительное» поведение, которое говорит о возможности типов сравнивать значения объектов.