Разница между Абстрактным классом и Интерфейсом является одним из популярных вопросов на собеседовании. Абстрактный класс и Интерфейс являются основной частью языка программирования Java. Выбор между интерфейсом и абстрактным классом – это решение дизайна, с которым сталкивается каждый архитектор. В своих последних статьях я предоставил как можно больше деталей о интерфейсе Java и абстрактном классе. В этом посте мы узнаем о разнице между абстрактным классом и интерфейсом и когда следует использовать интерфейс вместо абстрактного класса и наоборот.
Разница между Абстрактным классом и Интерфейсом
abstract
ключевое слово используется для создания абстрактного класса, и его можно использовать также с методами, тогда как ключевое словоinterface
используется для создания интерфейса и не может использоваться с методами.- Подклассы используют ключевое слово
extends
для расширения абстрактного класса, и им необходимо предоставить реализацию всех объявленных методов в абстрактном классе, если подкласс также не является абстрактным классом, тогда как подклассы используют ключевое словоimplements
для реализации интерфейсов и должны предоставить реализацию для всех методов, объявленных в интерфейсе. - Абстрактные классы могут содержать методы с реализацией, в то время как интерфейс обеспечивает абсолютную абстракцию и не может содержать реализации методов. Обратите внимание, что начиная с Java 8, мы можем создавать методы по умолчанию и статические методы в интерфейсе, которые содержат реализации методов.
- Абстрактные классы могут иметь конструкторы, но интерфейсы не могут иметь конструкторов.
- Абстрактный класс имеет все функции обычного класса Java, за исключением того, что мы не можем создать его экземпляр. Мы можем использовать ключевое слово
abstract
, чтобы сделать класс абстрактным, но интерфейсы являются совершенно другим типом и могут содержать только открытые статические константы и объявления методов. - Методы абстрактных классов могут иметь модификаторы доступа, такие как public, private, protected, static, но методы интерфейса являются неявно открытыми и абстрактными, мы не можем использовать другие модификаторы доступа с методами интерфейса.
- A subclass can extend only one abstract class but it can implement multiple interfaces.
- Абстрактные классы могут расширять другой класс и реализовывать интерфейсы, но интерфейс может только расширять другие интерфейсы.
- Мы можем выполнить абстрактный класс, если у него есть метод
main()
, но мы не можем выполнить интерфейс, потому что в них не может быть реализации метода main. - Интерфейсы используются для определения контракта для подклассов, тогда как абстрактный класс также определяет контракт, но может предоставлять реализацию других методов для использования подклассами.
Вот все для различия между интерфейсом и абстрактными классами, теперь мы можем перейти к вопросу, когда следует использовать интерфейс вместо абстрактного класса и наоборот.
Интерфейс или Абстрактный Класс
Выбор между интерфейсом и абстрактным классом для предоставления контракта подклассам – это решение дизайна и зависит от многих факторов. Давайте рассмотрим, когда Интерфейсы являются лучшим выбором и когда мы можем использовать абстрактные классы.
- Java не поддерживает множественное наследование на уровне класса, поэтому каждый класс может расширять только один суперкласс. Но класс может реализовывать несколько интерфейсов. Поэтому в большинстве случаев интерфейсы – это хороший выбор для предоставления базы для иерархии классов и контракта. Также программирование в терминах интерфейсов является одной из лучших практик программирования на Java.
- Если в контракте много методов, то абстрактный класс более полезен, потому что мы можем предоставить реализацию по умолчанию для некоторых методов, которые общи для всех подклассов. Также, если подклассам не нужно реализовывать определенный метод, они могут избежать предоставления реализации, в то время как в случае интерфейса подклассу придется предоставить реализацию для всех методов, даже если это бессмысленно, и реализация представляет собой только пустой блок.
- Если наш контракт постоянно меняется, то интерфейсы могут вызывать проблемы, потому что нельзя объявить дополнительные методы в интерфейсе, не изменяя все классы реализации. С абстрактным классом мы можем предоставить реализацию по умолчанию и изменить только те классы реализации, которые фактически будут использовать новые методы.
Используйте как абстрактные классы, так и интерфейсы
Использование интерфейсов и абстрактных классов вместе – лучший подход к проектированию системы. Например, в JDK java.util.List
является интерфейсом, который содержит множество методов, поэтому существует абстрактный класс java.util.AbstractList
, который предоставляет каркасную реализацию всех методов интерфейса List, так что любой подкласс может расширить этот класс и реализовать только необходимые методы. Мы всегда должны начинать с интерфейса в качестве базы и определять методы, которые должен реализовать каждый подкласс, а затем, если есть методы, которые должен реализовать только определенный подкласс, мы можем расширить базовый интерфейс и создать новый интерфейс с этими методами. Подклассам будет предоставлена возможность выбора между базовым интерфейсом и дочерним интерфейсом для реализации в соответствии с их требованиями. Если количество методов значительно увеличивается, не плохо предоставить каркасный абстрактный класс, реализующий дочерний интерфейс и обеспечивающий гибкость подклассам выбирать между интерфейсом и абстрактным классом.
Изменения в интерфейсе Java 8
С Java 8 и далее мы можем иметь реализации методов в интерфейсах. Мы можем создавать как методы по умолчанию, так и статические методы в интерфейсах и предоставлять для них реализацию. Это сократило разрыв между абстрактными классами и интерфейсами, и теперь интерфейсы – это путь к успеху, потому что мы можем расширить их дальше, предоставив реализации по умолчанию для новых методов. Для получения более подробной информации, ознакомьтесь с Методы по умолчанию и статические методы интерфейса Java 8.