Это может быть общий вопрос ООП. Я хотел сделать общее сравнение между интерфейсом и абстрактным классом на основе их использования.
Когда нужно использовать интерфейс, а когда - абстрактный класс ?
oop
inheritance
interface
abstract-class
Chirantan
источник
источник
Ответы:
Я написал статью об этом:
Абстрактные классы и интерфейсы
Подводя итог:
Когда мы говорим об абстрактных классах, мы определяем характеристики типа объекта; указав, что такое объект .
Когда мы говорим об интерфейсе и определяем возможности, которые мы обещаем предоставить, мы говорим об установлении договора о том, что может сделать объект.
источник
Interfaces do not express something like "a Doberman is a type of dog and every dog can walk" but more like "this thing can walk"
. СпасибоUse abstract classes and inheritance if you can make the statement “A is a B”. Use interfaces if you can make the statement “A is capable of [doing] as”
Абстрактный класс может иметь общее состояние или функциональность. Интерфейс - это только обещание предоставить состояние или функциональность. Хороший абстрактный класс уменьшит объем кода, который необходимо переписать, потому что его функциональность или состояние могут быть разделены. Интерфейс не имеет определенной информации для обмена
источник
Лично мне почти никогда не нужно писать абстрактные классы.
В большинстве случаев я вижу, что абстрактные классы используются (неправильно), потому что автор абстрактного класса использует шаблон «Шаблонный метод».
Проблема с «Методом шаблона» заключается в том, что он почти всегда несколько повторяется - «производный» класс знает не только о «абстрактном» методе своего базового класса, который он реализует, но и о открытых методах базового класса. , хотя в большинстве случаев это не нужно называть их.
(Чрезмерно упрощенный) пример:
Итак, здесь автор этого класса написал общий алгоритм и намеревается, чтобы люди использовали его, «специализируя» его, предоставляя свои собственные «крючки» - в данном случае, метод «сравнения».
Таким образом, предполагаемое использование примерно так:
Проблема в том, что вы неправильно связали воедино две концепции:
В приведенном выше коде теоретически автор метода «сравнение» может повторно вызывать метод «Сортировка» суперкласса ... даже на практике они никогда не захотят или не будут этого делать.
Цена, которую вы платите за эту ненужную связь, состоит в том, что трудно изменить суперкласс, и в большинстве языков OO невозможно изменить его во время выполнения.
Альтернативный метод - использовать шаблон проектирования «Стратегия»:
Итак, обратите внимание: все, что у нас есть, это интерфейсы и конкретные реализации этих интерфейсов. На практике вам больше ничего не нужно для создания ОО высокого уровня.
Чтобы «скрыть» тот факт, что мы реализовали «сортировку имен» с помощью класса «QuickSort» и «NameComparator», мы все равно могли бы написать метод фабрики:
Каждый раз, когда у вас есть абстрактный класс, вы можете сделать это ... даже когда между базовым и производным классом существуют естественные реентерабельные отношения, обычно стоит сделать их явными.
Одна заключительная мысль: все, что мы сделали выше, это «составление» функции «NameSorting» с использованием функции «QuickSort» и функции «NameComparison» ... на функциональном языке программирования этот стиль программирования становится еще более естественным, с меньшим количеством кода.
источник
Если вы смотрите на Java в качестве языка ООП,
« интерфейс не обеспечивает реализацию метода » больше не действует при запуске Java 8. Теперь Java предоставляет реализацию в интерфейсе для методов по умолчанию.
Проще говоря, я хотел бы использовать
интерфейс: для реализации контракта несколькими несвязанными объектами. Он обеспечивает возможность " HAS A ".
абстрактный класс: для реализации одинакового или разного поведения среди нескольких связанных объектов. Он устанавливает отношение " IS A ".
Oracle сайт предоставляет основные различия между
interface
иabstract
классом.Рассмотрите возможность использования абстрактных классов, если:
Рассмотрите возможность использования интерфейсов, если:
Serializable
интерфейс.Пример:
Абстрактный класс ( является соотношение)
Читатель - это абстрактный класс.
BufferedReader является
Reader
FileReader является
Reader
FileReader
иBufferedReader
используются для общей цели: чтение данных, и они связаны черезReader
класс.Интерфейс ( ИМЕЕТ возможность)
Сериализуемый это интерфейс.
Предположим, что у вас есть два класса в вашем приложении, которые реализуют
Serializable
интерфейсEmployee implements Serializable
Game implements Serializable
Здесь вы не можете установить какую-либо связь через
Serializable
интерфейс междуEmployee
иGame
, которые предназначены для разных целей. Оба способны сериализировать состояние, и сравнение на этом заканчивается.Посмотрите на эти сообщения:
Как мне объяснить разницу между интерфейсом и абстрактным классом?
источник
Хорошо, только что сам "проглотил" это - вот это с точки зрения непрофессионала (не стесняйтесь поправлять меня, если я ошибаюсь) - я знаю, что эта тема ооооооооочень, но кто-то другой может наткнуться на нее однажды ...
Абстрактные классы позволяют создавать чертежи и дополнительно КОНСТРУКТИВНО (реализовывать) свойства и методы, которые должны быть доступны ВСЕМ его потомкам.
Интерфейс, с другой стороны, позволяет вам только объявить, что вы хотите, чтобы свойства и / или методы с заданным именем существовали во всех классах, которые его реализуют, но не указывает, как вы должны это реализовать. Кроме того, класс может реализовывать МНОГО интерфейсов, но может расширять только ОДИН абстрактный класс. Интерфейс - это скорее высокоуровневый архитектурный инструмент (который становится понятнее, если вы начнете понимать шаблоны проектирования) - абстрактная работа в обоих лагерях позволяет выполнять некоторые грязные задачи.
Зачем использовать один над другим? Первое допускает более конкретное определение потомков - второе допускает больший полиморфизм . Этот последний пункт важен для конечного пользователя / кодера, который может использовать эту информацию для реализации AP I (интерфейса) в различных комбинациях / формах, чтобы удовлетворить их потребности.
Я думаю, что это был для меня момент «лампочки» - подумайте об интерфейсах меньше с точки зрения автора и больше с точки зрения любого кодера, который придет позже в цепочке, который добавляет реализацию в проект или расширяет API.
источник
Мои два цента:
Интерфейс в основном определяет контракт, которого должен придерживаться любой реализующий класс (реализовать элементы интерфейса). Он не содержит никакого кода.
С другой стороны, абстрактный класс может содержать код, и могут существовать некоторые методы, помеченные как абстрактные, которые должен реализовать наследующий класс.
Редкие ситуации, в которых я использовал абстрактные классы, это когда у меня есть некоторая функциональность по умолчанию, которую наследующий класс может не заинтересовать в переопределении, скажем, абстрактного базового класса, от которого наследуются некоторые специализированные классы.
Пример (очень зачаточном один!): Рассмотрим базовый класс с именем клиента , который имеет абстрактные методы , как
CalculatePayment()
,CalculateRewardPoints()
и некоторые не абстрактные методы , какGetName()
,SavePaymentDetails()
.Специализированные классы , как
RegularCustomer
иGoldCustomer
наследует отCustomer
базового класса и реализовать свои собственныеCalculatePayment()
иCalculateRewardPoints()
логику метода, но повторно использоватьGetName()
иSavePaymentDetails()
методы.Вы можете добавить больше функциональных возможностей к абстрактному классу (т.е. не абстрактным методам), не затрагивая дочерние классы, которые использовали более старую версию. Принимая во внимание, что добавление методов к интерфейсу повлияет на все классы, реализующие его, поскольку теперь им потребуется реализовать вновь добавленные члены интерфейса.
Абстрактный класс со всеми абстрактными членами будет похож на интерфейс.
источник
Когда делать то, что очень просто, если у вас в голове есть ясная концепция.
Абстрактные классы могут быть получены, тогда как интерфейсы могут быть реализованы. Есть некоторая разница между ними. Когда вы наследуете абстрактный класс, отношения между производным классом и базовым классом являются отношениями «это». Например, Собака - это Животное, Овца - это Животное, что означает, что производный класс наследует некоторые свойства от базового класса.
Принимая во внимание, что для реализации интерфейсов, отношение «может быть». например, собака может быть шпионской собакой. Собака может быть цирковой собакой. Собака может быть гоночной собакой. Это означает, что вы реализуете определенные методы для приобретения чего-либо.
Я надеюсь, что я ясно.
источник
1. Если вы создаете что-то, что предоставляет общие функциональные возможности несвязанным классам, используйте интерфейс.
2. Если вы создаете что-то для объектов, тесно связанных в иерархии, используйте абстрактный класс.
источник
Я написал статью о том, когда использовать абстрактный класс, а когда использовать интерфейс. Между ними существует гораздо больше различий, кроме "один IS-A ... и один CAN-DO ...". Для меня это консервированные ответы. Я упоминаю несколько причин, когда использовать любой из них. Надеюсь, поможет.
http://codeofdoom.com/wordpress/2009/02/12/learn-this-when-to-use-an-abstract-class-and-an-interface/
источник
Я думаю, что самый краткий способ выразить это следующим образом:
Общие свойства => абстрактный класс.
Общая функциональность => интерфейс.
И, если выразиться менее кратко ...
Пример абстрактного класса:
Поскольку у животных есть общее свойство - в данном случае количество ног - имеет смысл создать абстрактный класс, содержащий это общее свойство. Это также позволяет нам писать общий код, который работает с этим свойством. Например:
Пример интерфейса:
Обратите внимание, что Vuvuzelas и Cars - это совершенно разные вещи, но они имеют общую функциональность: создание звука. Таким образом, интерфейс имеет смысл здесь. Кроме того, это позволит программистам группировать вещи, которые издают звуки, в едином интерфейсе -
IMakeSound
в данном случае. С этим дизайном вы могли бы написать следующий код:Можете ли вы сказать, что это будет выводить?
Наконец, вы можете объединить два.
Комбинированный пример:
Здесь мы требуем, чтобы все
BaseAnimal
сделали звук, но мы еще не знаем его реализацию. В таком случае мы можем абстрагировать реализацию интерфейса и делегировать его реализацию его подклассам.Еще один момент, помните, как в примере с абстрактным классом мы могли работать с общими свойствами различных объектов, а в примере интерфейса мы могли вызывать общую функциональность различных объектов? В этом последнем примере мы могли бы сделать оба.
источник
Когда предпочитать абстрактный класс интерфейсу?
Когда предпочитать интерфейс над абстрактным классом?
источник
Классы могут наследовать только от одного базового класса, поэтому, если вы хотите использовать абстрактные классы для обеспечения полиморфизма для группы классов, все они должны наследовать от этого класса. Абстрактные классы также могут предоставлять члены, которые уже были реализованы. Следовательно, вы можете обеспечить определенное количество идентичных функциональных возможностей с помощью абстрактного класса, но не можете с помощью интерфейса.
Вот несколько рекомендаций, которые помогут вам решить, использовать ли интерфейс или абстрактный класс для полиморфизма ваших компонентов.
Скопировано с:
http://msdn.microsoft.com/en-us/library/scsyfw1d%28v=vs.71%29.aspx
источник
Рассмотрите возможность использования абстрактных классов, если любое из этих утверждений применимо к вашей ситуации:
Рассмотрите возможность использования интерфейсов, если любое из этих утверждений применимо к вашей ситуации:
Источник
источник
Ответы различаются в зависимости от языка. Например, в Java класс может реализовывать (наследовать) несколько интерфейсов, но наследовать только от одного абстрактного класса. Таким образом, интерфейсы дают вам больше гибкости. Но это не так в C ++.
источник
Для меня я бы пошел с интерфейсами во многих случаях. Но я предпочитаю абстрактные классы в некоторых случаях.
Классы в ОО вообще относятся к реализации. Я использую абстрактные классы, когда хочу навязать некоторые детали реализации дочерним элементам, иначе я использую интерфейсы.
Конечно, абстрактные классы полезны не только для принудительной реализации, но и для обмена некоторыми конкретными деталями между многими связанными классами.
источник
Используйте абстрактный класс, если вы хотите предоставить некоторые базовые реализации.
источник
в Java вы можете наследовать от одного (абстрактного) класса, чтобы «обеспечить» функциональность, и вы можете реализовать много интерфейсов, чтобы «обеспечить» функциональность
источник
Чисто на основе наследования вы будете использовать реферат, в котором вы определяете явно наследуемые, абстрактные отношения (например, animal-> cat) и / или требуете наследования виртуальных или непубличных свойств, особенно общего состояния (которое интерфейсы не могут поддерживать). ).
Вы должны попытаться отдать предпочтение композиции (посредством внедрения зависимостей), а не наследованию, и заметьте, что интерфейсы, являющиеся контрактами, поддерживают модульное тестирование, разделение проблем и (в зависимости от языка) множественное наследование таким образом, каким не могут абстрагироваться.
источник
Одно интересное место, где интерфейсы работают лучше, чем абстрактные классы, это когда вам нужно добавить дополнительную функциональность в группу (связанных или не связанных) объектов. Если вы не можете дать им базовый абстрактный класс (например, они имеют
sealed
или уже имеют родителя), вы можете вместо этого дать им фиктивный (пустой) интерфейс, а затем просто написать методы расширения для этого интерфейса.источник
Это может быть очень сложный вызов ...
Один указатель, который я могу дать: объект может реализовать много интерфейсов, в то время как объект может наследовать только один базовый класс (в современном языке OO, таком как c #, я знаю, что C ++ имеет множественное наследование - но разве это не осуждается?)
источник
Абстрактный класс может иметь реализации.
Интерфейс не имеет реализаций, он просто определяет вид контракта.
Также могут быть некоторые языковые различия: например, C # не имеет множественного наследования, но в классе может быть реализовано несколько интерфейсов.
источник
Основное правило большого пальца: для "Существительных" используйте абстрактный класс, а для "Глаголов" используйте интерфейс
Например:
car
это абстрактный класс, иdrive
мы можем сделать его интерфейсом.источник
drive
в автомобиль - это абстрактный класс.