Допустим, у нас есть абстрактный класс, и пусть этот класс имеет только абстрактные методы. Отличается ли этот абстрактный класс от интерфейса, который имеет только те же методы?
Я хочу знать, есть ли какие-либо различия как в философском, объективном, так и в базовой реализации языка программирования между абстрактным классом только с абстрактными членами и эквивалентным интерфейсом?
Ответы:
Технически, различия не очень значительны, но концептуально это совершенно разные вещи, и это приводит к техническим различиям, о которых упоминали другие.
Абстрактный суперкласс - это именно то, на что он похож, это общий тип, который разделяют многие другие типы, например, Кошки и Собаки - Животные.
Интерфейс - это также то, на что он похож, это интерфейс, через который другие классы могут взаимодействовать с объектом. Если вы хотите сделать Cat Walk, вы в порядке, потому что Cat реализует интерфейс CanWalk. То же самое для Ящерицы, хотя они ходят совсем по-другому. Снейк, с другой стороны, не реализует CanWalk, поэтому вы не можете передать его Walk. Между тем, Lizard и Snake (или, возможно, более явные подклассы - я не эксперт) могли бы сбросить свой скин и, таким образом, реализовать CanShed, в то время как Cat не мог этого сделать.
Но они все еще животные и имеют некоторые общие свойства, например, живы они или мертвы.
Вот почему все методы интерфейса должны быть реализованы как общедоступные (или явно в C #). Потому что какой смысл в интерфейсе, который скрыт от класса, взаимодействующего с объектом? Именно поэтому вы можете иметь несколько интерфейсов для объекта, даже если язык не поддерживает множественное наследование.
Возвращаясь к вашему вопросу, когда вы смотрите на него с такой точки зрения, очень редко есть причина иметь полностью абстрактный суперкласс.
источник
В большинстве языков ООП реализующий класс может быть производным только от одного абстрактного класса, но реализовывать несколько интерфейсов.
источник
В языке, подобном C ++, который допускает множественное наследование и не имеет интерфейсов, абстрактные классы, в которых все методы являются абстрактными, могут служить интерфейсами. Я не так много работал с C ++, но, полагаю, множественное наследование может вызвать проблемы, когда в базовых классах есть методы с одинаковыми именами.
В таких языках, как PHP и C #, интерфейсы предоставляют средства для достижения аналогичного полиморфизма, хотя мне не нравится называть это «наследованием», поскольку существует концептуальная разница между наследованием абстрактного класса и реализацией интерфейса. Интерфейсы устраняют проблему конфликта, потому что они сами не обеспечивают реализацию.
Интерфейс служит контрактом с внешним миром, в то время как абстрактный класс может обеспечивать реализацию, хотя, если он используется для «подделки» интерфейса, он, скорее всего, не будет.
Основное концептуальное отличие состоит в том, что когда класс наследует другой класс (абстрактный или нет), возникает отношение «есть», поэтому «а»
Car
есть «а»Vehicle
и «Dog
есть»Animal
. С интерфейсом важно то, что делает объект. Таким образом,Car
иDog
может,Move()
и потребитель знает это, потому что они реализуютMovable
, но Автомобиль определенно неDog
, илиAnimal
. И реализация перемещения будет отличаться (колеса против ног), но код потребления не заботится и не должен волноваться. Интерфейсы все о потреблении кода, а не о реализации.Главное, если у вас есть интерфейсы на выбранном вами языке, используйте их для вещей, для которых они существуют. Если нет (как в C ++), вы можете подделать их, используя чисто абстрактные классы.
источник
Dog
иCat
есть, и есть .Абстрактные классы могут содержать абстрактные защищенные методы (на языках, с которыми я работаю), в интерфейсах методы обычно всегда общедоступны. Допускает ли это различие полезную эксплуатацию, я не знаю.
Править Сначала я думал, что закрытый абстрактный метод бесполезен, но теперь я вспомнил, что его можно использовать, чтобы этот метод никогда не вызывался. Таким образом, вы можете предотвратить вызов конструктора копирования объекта.
источник
Да, они разные. В противном случае дизайнеры языка не предоставили бы и то и другое. Я знаю два языка, которые разделяют классы и интерфейсы: Java и C #, мутантный клон Java. Дизайнеры создали интерфейсы, чтобы избежать поддержки множественного наследования классов. Большинство других языков поддерживают множественное наследование классов и, следовательно, не разделяют классы и интерфейсы.
источник
Я думаю, что основное отличие состоит в том, что: в абстрактном классе - даже если все методы являются абстрактными, они все же могут предоставлять члены данных (переменные экземпляра) и некоторый код классам, которые его реализуют (в форме частных методов или конструкторов), статические блоки; выполнять часть работы для подклассов и помогать им в реализации.
Один положительный побочный эффект: код находится в одном месте, поэтому в одном месте можно вносить исправления. подклассы могут просто вызывать метод суперкласса и затем делать что-то еще или ничего, если для их случая достаточно действий суперкласса. Суперкласс хочет, чтобы каждый подкласс принимал это решение, поэтому пометил всю его реализацию как абстрактную (некоторые тоже могут быть пустыми)
Не относится к вопросу: но наличие интерфейсов означает, что один класс может реализовывать два разных контракта. Так что это преимущество интерфейса перед абстрактным суперклассом
источник