Интерфейс против абстрактного класса (общий ОО)

A ClassCircularityError бросается, когда некоторый класс является (косвенным) суперклассом самого себя, некоторый интерфейс (косвенно) распространяется сам или аналогичный.

Это обычно не должно происходить, поскольку хорошо продуманный компилятор будет не создавать такие классы, но использование разных версий библиотеки (или использование нескольких библиотек, содержащих разные версии класса) может привести к этой проблеме.

Сканирование ваших библиотек для имен двойных классов, в частности, посмотрите, существует несколько версий упомянутого класса org.apache.commons.codec.binary.Hex.

1339
задан Community 23 May 2017 в 12:34
поделиться

11 ответов

While your question indicates it's for "general OO", it really seems to be focusing on .NET use of these terms.

In .NET (similar for Java):

  • interfaces can have no state or implementation
  • a class that implements an interface must provide an implementation of all the methods of that interface
  • abstract classes may contain state (data members) and/or implementation (methods)
  • abstract classes can be inherited without implementing the abstract methods (though such a derived class is abstract itself)
  • interfaces may be multiple-inherited, abstract classes may not (this is probably the key concrete reason for interfaces to exist separately from abtract classes - they permit an implementation of multiple inheritance that removes many of the problems of general MI).

As general OO terms, the differences are not necessarily well-defined. For example, there are C++ programmers who may hold similar rigid definitions (interfaces are a strict subset of abstract classes that cannot contain implementation), while some may say that an abstract class with some default implementations is still an interface or that a non-abstract class can still define an interface.

Indeed, there is a C++ idiom called the Non-Virtual Interface (NVI) where the public methods are non-virtual methods that 'thunk' to private virtual methods:

723
ответ дан 19 December 2019 в 20:15
поделиться

1) Интерфейс можно рассматривать как чистый абстрактный класс, он такой же, но, несмотря на это, не То же самое для реализации интерфейса и наследования от абстрактного класса. Когда вы наследуете от этого чистого абстрактного класса, вы определяете иерархию -> наследование, если вы реализуете интерфейс, которым вы не являетесь, и вы можете реализовать столько интерфейсов, сколько хотите, но вы можете наследовать только от одного класса.

2 ) Вы можете определить свойство в интерфейсе, поэтому класс, реализующий этот интерфейс, должен иметь это свойство.

Например:

  public interface IVariable
  {
      string name {get; set;}
  }

Класс, реализующий этот интерфейс, должен иметь такое свойство.

7
ответ дан 19 December 2019 в 20:15
поделиться

Из другого моего ответа , в основном касающегося того, когда использовать один против другого:

По моему опыту, интерфейсы лучше используется, когда у вас есть несколько классов на который каждый должен ответить одинаково метод или методы, чтобы они могли быть используется взаимозаменяемо другим кодом который будет написан против тех, общий интерфейс классов. Лучший использование интерфейса, когда Протокол важен, но лежащая в основе логика может отличаться для каждый класс. Если бы вы были иначе дублирующая логика, рассмотрим абстрактный классы или стандартное наследование классов вместо этого.

5
ответ дан 19 December 2019 в 20:15
поделиться

Интервьюеры лают странное дерево. Для языков, таких как C # и Java, есть разница, но в других языках, таких как C ++, нет. Теория ОО не различает их, а только синтаксис языка.

Абстрактный класс - это класс с реализацией и интерфейсом (чисто виртуальные методы), которые будут наследоваться. Интерфейсы обычно не имеют никакой реализации, а только чисто виртуальные функции.

В C # или Java абстрактный класс без какой-либо реализации отличается от интерфейса только синтаксисом, используемым для его наследования, и тем фактом, что вы можете наследовать только от одного.

32
ответ дан 19 December 2019 в 20:15
поделиться

Для .Net,

Ваш ответ Второму интервьюеру также является ответом на первый ... Абстрактные классы могут иметь реализация, состояние И, интерфейсы не могут ...

РЕДАКТИРОВАТЬ: С другой стороны, я бы даже не стал использовать фразу «подкласс» (или фразу «наследование») для описания классов, которые «определены для реализации» интерфейса . Для меня интерфейс - это определение контракта, которому должен соответствовать класс, если он был определен для «реализации» этого интерфейса. Он ничего не наследует ... Вы должны добавить все сами, явно.

21
ответ дан 19 December 2019 в 20:15
поделиться

Реализуя интерфейсы, вы получаете композицию (отношения has-a) вместо наследования (is-a) отношения). Это важный принцип, который нужно помнить, когда речь заходит о таких вещах, как шаблоны проектирования, где вам нужно использовать интерфейсы для достижения композиции поведения вместо наследования.

31
ответ дан 19 December 2019 в 20:15
поделиться

пара других отличий -

Интерфейсы не могут иметь никаких конкретных реализаций. Абстрактные базовые классы могут. Это позволяет вам предоставлять конкретные реализации там. Это может позволить абстрактному базовому классу фактически предоставить более строгий контракт, тогда как интерфейс действительно только описывает, как используется класс. (Абстрактный базовый класс может иметь не виртуальные члены, определяющие поведение, что дает больше контроля автору базового класса.)

В классе может быть реализовано более одного интерфейса. Класс может быть производным только от одного абстрактного базового класса. Это допускает полиморфную иерархию с использованием интерфейсов, но не абстрактных базовых классов. Это также позволяет использовать псевдо-мульти-наследование с использованием интерфейсов.

Абстрактные базовые классы могут быть изменены в v2 + без нарушения API. Изменения в интерфейсах разрушают изменения.

[C # /. NET Specific] Интерфейсы, в отличие от абстрактных базовых классов, могут применяться к типам значений (структурам). Структуры не могут наследоваться от абстрактных базовых классов. Это позволяет применять поведенческие контракты / руководства по использованию к типам значений.

77
ответ дан 19 December 2019 в 20:15
поделиться

Ответ на второй вопрос: общедоступная переменная, определенная в интерфейсе , по умолчанию является статическим окончанием , а общедоступной Переменная в классе abstract является переменной экземпляра.

6
ответ дан 19 December 2019 в 20:15
поделиться

Интерфейсы являются легкими способом для обеспечения определенного поведения. Это один из способов думать о.

9
ответ дан 19 December 2019 в 20:15
поделиться

Пара других различий:

Абстрактные классы могут иметь статические методы, свойства, поля и т.д. и операторы, а интерфейсы - нет. Оператор Cast позволяет приводить к/от абстрактного класса, но не позволяет приводить к/от интерфейса.

Таким образом, в основном вы можете использовать абстрактный класс сам по себе, даже если он никогда не будет реализован (через его статические члены), а интерфейс вы не можете использовать сам по себе ни в коем случае.

3
ответ дан 19 December 2019 в 20:15
поделиться

Как насчет аналогии: когда я служил в ВВС, я пошел на обучение пилотов и стал пилотом ВВС США (ВВС США). В тот момент у меня не было квалификации летать на чем-либо, и мне пришлось пройти обучение по типам самолетов. После квалификации я был пилотом (абстрактный класс) и пилотом C-141 (конкретный класс). На одном из моих назначений мне дали дополнительную обязанность: Офицер безопасности. Теперь я был еще пилотом и пилотом С-141, но я также выполнял обязанности офицера безопасности (я внедрил, так сказать, ISafetyOfficer). От пилота не требовалось быть офицером безопасности, это могли делать и другие люди.

Все пилоты ВВС США должны следовать определенным правилам ВВС, и все пилоты C-141 (или F-16, или Т-38) «являются» пилотами ВВС США. Любой может быть офицером безопасности. Итак, резюмируем:

  • Пилот: абстрактный класс
  • Пилот C-141: конкретный класс
  • Сотрудник службы безопасности: интерфейс

добавлено примечание: это должно было быть аналогией, чтобы помочь объяснить концепцию, а не рекомендация по кодировке. См. различные комментарии ниже, обсуждение интересное.

843
ответ дан 19 December 2019 в 20:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: