Мне задали вопрос, я хотел, чтобы мой ответ был рассмотрен здесь.
В : В каком сценарии более целесообразно расширить абстрактный класс, а не реализовывать интерфейс (ы)?
О: Если мы используем шаблонный метод проектирования.
Я прав ?
Прошу прощения, если я не смог четко сформулировать вопрос.
Я знаю основную разницу между абстрактным классом и интерфейсом.
1) использовать абстрактный класс, когда требование таково, что нам нужно реализовать одну и ту же функциональность в каждом подклассе для конкретной операции (реализовать метод) и разные функции для некоторых других операций (только сигнатуры методов)
2) используйте интерфейс, если вам нужно поставить такую же подпись (и другую реализацию), чтобы вы могли соответствовать реализации интерфейса
3) мы можем расширить максимум одного абстрактного класса, но можем реализовать более одного интерфейса
Повторяем вопрос: существуют ли какие-либо другие сценарии, помимо упомянутых выше, в которых мы конкретно требуем использовать абстрактный класс (один из них - это то, что шаблон проектирования метода шаблонов концептуально основан только на этом)?
Интерфейс против абстрактного класса
Выбор между этими двумя действительно зависит от того, что вы хотите сделать, но, к счастью для нас, Эрих Гамма может нам немного помочь.
Как всегда, есть компромисс, интерфейс дает вам свободу в отношении базового класса, абстрактный класс дает вам свободу добавлять новые методы позже . - Эрих Гамма
Вы не можете пойти и изменить интерфейс, не изменив множество других вещей в вашем коде, поэтому единственный способ избежать этого - создать полностью новый интерфейс, что не всегда может быть хорошо.
Abstract classes
в первую очередь следует использовать для тесно связанных объектов. Interfaces
лучше предоставляют общие функции для несвязанных классов.
Ответы:
Когда использовать интерфейсы
Интерфейс позволяет кому-то начать с нуля, чтобы реализовать ваш интерфейс или реализовать ваш интерфейс в каком-либо другом коде, первоначальная или основная цель которого сильно отличалась от вашего интерфейса. Для них ваш интерфейс - всего лишь случайность, что-то, что нужно добавить в их код, чтобы иметь возможность использовать ваш пакет. Недостатком является то, что каждый метод в интерфейсе должен быть общедоступным. Возможно, вы не захотите раскрывать все.
Когда использовать абстрактные классы
Абстрактный класс, напротив, предоставляет больше структуры. Обычно он определяет некоторые реализации по умолчанию и предоставляет некоторые инструменты, полезные для полной реализации. Загвоздка в том, что код, использующий его, должен использовать ваш класс в качестве основы. Это может быть очень неудобно, если другие программисты, желающие использовать ваш пакет, уже независимо разработали свою собственную иерархию классов. В Java класс может наследовать только от одного базового класса.
Когда использовать оба
Вы можете предложить лучшее из обоих миров, интерфейс и абстрактный класс. Разработчики могут игнорировать ваш абстрактный класс, если захотят. Единственный недостаток в том, что вызов методов через имя их интерфейса немного медленнее, чем их вызов через имя абстрактного класса.
источник
If we are using template method design pattern
Мы не можем сказатьYES
илиNO
Да, если вы используете JAXB. Не любит интерфейсы. Вы должны либо использовать абстрактные классы, либо обойти это ограничение с помощью универсальных шаблонов.
Из личного блога пост :
Интерфейс:
В общем, интерфейсы должны использоваться для определения контрактов (что должно быть достигнуто, а не как этого достичь).
Абстрактный класс:
Для (частичной) реализации следует использовать абстрактные классы. Они могут быть средством ограничения способа реализации контрактов API.
источник
default
иstatic
методы тоже.Интерфейс используется, когда у вас есть сценарий, в котором все классы имеют одинаковую структуру, но имеют совершенно разные функции.
Абстрактный класс используется, когда у вас есть сценарий, в котором все классы имеют одинаковую структуру, но некоторые одинаковые и некоторые разные функции.
Взгляните на статью: http://shoaibmk.blogspot.com/2011/09/abstract-class-is-class-which-cannot-be.html
источник
Здесь есть много отличных ответов, но я часто нахожу использование ОБЕИ интерфейсов и абстрактных классов лучшим путем. Рассмотрим этот надуманный пример:
Вы разработчик программного обеспечения в инвестиционном банке и вам необходимо создать систему, которая размещает заказы на рынке. Ваш интерфейс отражает самое общее представление о том, что делает торговая система ,
1) Trading system places orders 2) Trading system receives acknowledgements
и может быть захвачен в интерфейсе,
ITradeSystem
public interface ITradeSystem{ public void placeOrder(IOrder order); public void ackOrder(IOrder order); }
Теперь инженеры, работающие в отделе продаж и других направлениях бизнеса, могут начать взаимодействовать с вашей системой, чтобы добавить функциональность размещения заказов в свои существующие приложения. И вы еще даже не начали строить! В этом сила интерфейсов.
Итак, вы продолжаете создавать систему для биржевых трейдеров; они слышали, что в вашей системе есть функция поиска дешевых товаров, и очень хотят попробовать ее! Вы фиксируете это поведение с помощью вызываемого метода
findGoodDeals()
, но при этом понимаете, что при подключении к рынкам задействовано много беспорядка. Например, вам нужно открытьSocketChannel
,public class StockTradeSystem implements ITradeSystem{ @Override public void placeOrder(IOrder order); getMarket().place(order); @Override public void ackOrder(IOrder order); System.out.println("Order received" + order); private void connectToMarket(); SocketChannel sock = Socket.open(); sock.bind(marketAddress); <LOTS MORE MESSY CODE> } public void findGoodDeals(); deals = <apply magic wizardry> System.out.println("The best stocks to buy are: " + deals); }
В конкретных реализациях будет много таких грязных методов
connectToMarket()
, ноfindGoodDeals()
это все, что действительно волнует трейдеров.А теперь в игру вступают абстрактные классы. Ваш босс сообщает вам, что валютные трейдеры также хотят использовать вашу систему. И глядя на валютные рынки, вы видите, что водопровод почти идентичен фондовым рынкам. Фактически,
connectToMarket()
можно дословно повторно использовать для подключения к валютным рынкам. ОднакоfindGoodDeals()
на валютной арене это совсем другая концепция. Поэтому, прежде чем передать кодовую базу парню-валютному магу через океан, вы сначала реорганизуетеabstract
класс, оставляяfindGoodDeals()
нереализованныеpublic abstract class ABCTradeSystem implements ITradeSystem{ public abstract void findGoodDeals(); @Override public void placeOrder(IOrder order); getMarket().place(order); @Override public void ackOrder(IOrder order); System.out.println("Order received" + order); private void connectToMarket(); SocketChannel sock = Socket.open(); sock.bind(marketAddress); <LOTS MORE MESSY CODE> }
Ваша система торговли акциями реализует,
findGoodDeals()
как вы уже определили,public class StockTradeSystem extends ABCTradeSystem{ public void findGoodDeals(); deals = <apply magic wizardry> System.out.println("The best stocks to buy are: " + deals); }
но теперь вундеркинд FX может построить свою систему, просто предоставив реализацию
findGoodDeals()
для валют; ей не нужно заново реализовывать соединения сокетов или даже методы интерфейса!public class CurrencyTradeSystem extends ABCTradeSystem{ public void findGoodDeals(); ccys = <Genius stuff to find undervalued currencies> System.out.println("The best FX spot rates are: " + ccys); }
Программирование для интерфейса - это мощное средство, но похожие приложения часто повторно реализуют методы почти одинаковыми способами. Использование абстрактного класса позволяет избежать повторных реализаций, сохраняя при этом мощь интерфейса.
Примечание: можно задаться вопросом, почему
findGreatDeals()
не является частью интерфейса. Помните, что интерфейс определяет самые общие компоненты торговой системы. Другой инженер может разработать СОВЕРШЕННО ДРУГУЮ торговую систему, в которой он не заботится о поиске хороших сделок. Интерфейс гарантирует, что отдел продаж также может взаимодействовать со своей системой, поэтому желательно не связывать ваш интерфейс с концепциями приложения, такими как «выгодные предложения».источник
Что вам следует использовать, абстрактные классы или интерфейсы?
Рассмотрите возможность использования абстрактных классов, если любое из этих утверждений применимо к вашему варианту использования:
Вы хотите разделить код между несколькими тесно связанными классами.
Вы ожидаете, что классы, расширяющие ваш абстрактный класс, имеют много общих методов или полей или требуют модификаторов доступа, отличных от общедоступных (таких как защищенный и частный).
Вы хотите объявить нестатические или неокончательные поля. Это позволяет вам определять методы, которые могут получать доступ и изменять состояние объекта, которому они принадлежат.
Рассмотрите возможность использования интерфейсов, если любое из этих утверждений применимо к вашему варианту использования:
Вы ожидаете, что несвязанные классы будут реализовывать ваш интерфейс. Например, интерфейсы Comparable и Cloneable реализуются многими несвязанными классами.
Вы хотите указать поведение определенного типа данных, но не беспокоитесь о том, кто реализует его поведение.
Вы хотите воспользоваться преимуществами множественного наследования типа.
http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
источник
Вещи сильно изменились за последние три года с добавлением новых возможностей интерфейса с версией Java 8.
Со страницы документации Oracle по интерфейсу:
Как вы указали в своем вопросе, абстрактный класс лучше всего подходит для шаблона метода шаблона, где вам нужно создать каркас. Интерфейс здесь использовать нельзя.
Еще одно соображение, чтобы предпочесть абстрактный класс интерфейсу:
У вас нет реализации в базовом классе, и только подклассы должны определять свою собственную реализацию. Вам нужен абстрактный класс вместо интерфейса, поскольку вы хотите поделиться состоянием с подклассами.
Абстрактный класс устанавливает связь между связанными классами, а интерфейс предоставляет возможность "имеет" между несвязанными классами .
Что касается второй части вашего вопроса, которая действительна для большинства языков программирования, включая java, до выпуска java-8
Если вы предпочитаете абстрактный класс для интерфейса ранее с двумя вышеупомянутыми соображениями, вам нужно переосмыслить сейчас, поскольку методы по умолчанию добавили мощные возможности для интерфейсов.
Чтобы выбрать один из них между интерфейсом и абстрактным классом, на странице документации оракула цитируется следующее:
Обратитесь к этим связанным вопросам для получения более подробной информации:
Интерфейс против абстрактного класса (общий объектно-ориентированный подход)
Как мне объяснить разницу между интерфейсом и абстрактным классом?
Подводя итог: теперь баланс больше смещается в сторону интерфейсов .
Некоторые шаблоны проектирования используют абстрактные классы (поверх интерфейсов) помимо шаблона метода шаблона.
Шаблоны создания:
Abstract_factory_pattern
Структурные образцы:
Decorator_pattern
Модели поведения:
Mediator_pattern
источник
Вы не правы. Есть много сценариев. Просто невозможно свести его к одному правилу из 8 слов.
источник
Самый короткий ответ - расширять абстрактный класс, если в нем уже реализованы некоторые функции, которые вы ищете.
Если вы реализуете интерфейс, вы должны реализовать весь метод. Но для абстрактного класса количество методов, которые вам нужно реализовать, может быть меньше.
В шаблоне дизайна шаблона должно быть определено поведение. Это поведение зависит от других абстрактных методов. Создавая подкласс и определяя эти методы, вы фактически определяете основное поведение. Базовое поведение не может быть в интерфейсе, поскольку интерфейс ничего не определяет, он просто объявляет. Таким образом, шаблон проектирования всегда имеет абстрактный класс. Если вы хотите сохранить последовательность поведения без изменений, вы должны расширить абстрактный класс, но не переопределять основное поведение.
источник
Pure virtual functions can also be used where the method declarations are being used to define an interface - similar to what the interface keyword in Java explicitly specifies. In such a use, derived classes will supply all implementations. In such a design pattern, the abstract class which serves as an interface will contain only pure virtual functions, but no data members or ordinary methods.
часть (1/2)no data members or ordinary methods
[в абстрактном классе].На мой взгляд, основная разница в том
an interface can't contain non abstract methods while an abstract class can
. Таким образом, если подклассы имеют общее поведение, это поведение может быть реализовано в суперклассе и, таким образом, унаследовано в подклассах.Также я процитировал следующее из книги "Шаблоны проектирования архитектуры программного обеспечения в java"
«В языке программирования Java нет поддержки множественного наследования. Это означает, что класс может наследовать только от одного-единственного класса. Следовательно, наследование следует использовать только тогда, когда это абсолютно необходимо. По возможности, методы, обозначающие общее поведение, должны быть объявлены в форма интерфейса Java, который должен быть реализован различными классами разработчиков. Но интерфейсы страдают от ограничения, заключающегося в том, что они не могут предоставлять реализации методов. Это означает, что каждый разработчик интерфейса должен явно реализовать все методы, объявленные в интерфейсе, даже если некоторые из них методы представляют собой неизменную часть функциональности и имеют одинаковую реализацию во всех классах средств реализации, что приводит к избыточному коду.В следующем примере показано, как можно использовать шаблон абстрактного родительского класса в таких случаях, не требуя реализации избыточных методов ».
источник
Абстрактные классы отличаются от интерфейсов двумя важными аспектами
источник
Это хороший вопрос. Эти два вопроса не похожи, но могут использоваться по одной и той же причине, например, для перезаписи. При создании лучше всего использовать Интерфейс. Когда дело доходит до класса, это хорошо для отладки.
источник
Abstract classes should be extended when you want to some common behavior to get extended
. Суперкласс Abstract будет иметь общее поведение и будет определять абстрактный метод / конкретное поведение, которое должны реализовывать подклассы.Interfaces allows you to change the implementation anytime allowing the interface to be intact
.источник
Это мое понимание, надеюсь, это поможет
Абстрактные классы:
Интерфейсы:
источник
Использование аннотации и интерфейса:
У одного есть "есть-отношения", а у другого "есть-отношения".
Свойства по умолчанию заданы абстрактно, а дополнительные свойства могут быть выражены через интерфейс.
Пример: -> В человеческих существах у нас есть некоторые свойства по умолчанию, такие как еда, сон и т. Д., Но если у кого-то есть другие учебные занятия, такие как плавание, игра и т. Д., Они могут быть выражены интерфейсом.
источник