A ClassCircularityError
бросается, когда некоторый класс является (косвенным) суперклассом самого себя, некоторый интерфейс (косвенно) распространяется сам или аналогичный.
Это обычно не должно происходить, поскольку хорошо продуманный компилятор будет не создавать такие классы, но использование разных версий библиотеки (или использование нескольких библиотек, содержащих разные версии класса) может привести к этой проблеме.
Сканирование ваших библиотек для имен двойных классов, в частности, посмотрите, существует несколько версий упомянутого класса org.apache.commons.codec.binary.Hex
.
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):
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:
1) Интерфейс можно рассматривать как чистый абстрактный класс, он такой же, но, несмотря на это, не То же самое для реализации интерфейса и наследования от абстрактного класса. Когда вы наследуете от этого чистого абстрактного класса, вы определяете иерархию -> наследование, если вы реализуете интерфейс, которым вы не являетесь, и вы можете реализовать столько интерфейсов, сколько хотите, но вы можете наследовать только от одного класса.
2 ) Вы можете определить свойство в интерфейсе, поэтому класс, реализующий этот интерфейс, должен иметь это свойство.
Например:
public interface IVariable
{
string name {get; set;}
}
Класс, реализующий этот интерфейс, должен иметь такое свойство.
Из другого моего ответа , в основном касающегося того, когда использовать один против другого:
По моему опыту, интерфейсы лучше используется, когда у вас есть несколько классов на который каждый должен ответить одинаково метод или методы, чтобы они могли быть используется взаимозаменяемо другим кодом который будет написан против тех, общий интерфейс классов. Лучший использование интерфейса, когда Протокол важен, но лежащая в основе логика может отличаться для каждый класс. Если бы вы были иначе дублирующая логика, рассмотрим абстрактный классы или стандартное наследование классов вместо этого.
Интервьюеры лают странное дерево. Для языков, таких как C # и Java, есть разница, но в других языках, таких как C ++, нет. Теория ОО не различает их, а только синтаксис языка.
Абстрактный класс - это класс с реализацией и интерфейсом (чисто виртуальные методы), которые будут наследоваться. Интерфейсы обычно не имеют никакой реализации, а только чисто виртуальные функции.
В C # или Java абстрактный класс без какой-либо реализации отличается от интерфейса только синтаксисом, используемым для его наследования, и тем фактом, что вы можете наследовать только от одного.
Для .Net,
Ваш ответ Второму интервьюеру также является ответом на первый ... Абстрактные классы могут иметь реализация, состояние И, интерфейсы не могут ...
РЕДАКТИРОВАТЬ: С другой стороны, я бы даже не стал использовать фразу «подкласс» (или фразу «наследование») для описания классов, которые «определены для реализации» интерфейса . Для меня интерфейс - это определение контракта, которому должен соответствовать класс, если он был определен для «реализации» этого интерфейса. Он ничего не наследует ... Вы должны добавить все сами, явно.
Реализуя интерфейсы, вы получаете композицию (отношения has-a) вместо наследования (is-a) отношения). Это важный принцип, который нужно помнить, когда речь заходит о таких вещах, как шаблоны проектирования, где вам нужно использовать интерфейсы для достижения композиции поведения вместо наследования.
пара других отличий -
Интерфейсы не могут иметь никаких конкретных реализаций. Абстрактные базовые классы могут. Это позволяет вам предоставлять конкретные реализации там. Это может позволить абстрактному базовому классу фактически предоставить более строгий контракт, тогда как интерфейс действительно только описывает, как используется класс. (Абстрактный базовый класс может иметь не виртуальные члены, определяющие поведение, что дает больше контроля автору базового класса.)
В классе может быть реализовано более одного интерфейса. Класс может быть производным только от одного абстрактного базового класса. Это допускает полиморфную иерархию с использованием интерфейсов, но не абстрактных базовых классов. Это также позволяет использовать псевдо-мульти-наследование с использованием интерфейсов.
Абстрактные базовые классы могут быть изменены в v2 + без нарушения API. Изменения в интерфейсах разрушают изменения.
[C # /. NET Specific] Интерфейсы, в отличие от абстрактных базовых классов, могут применяться к типам значений (структурам). Структуры не могут наследоваться от абстрактных базовых классов. Это позволяет применять поведенческие контракты / руководства по использованию к типам значений.
Ответ на второй вопрос: общедоступная
переменная, определенная в интерфейсе
, по умолчанию является статическим окончанием
, а общедоступной Переменная
в классе abstract
является переменной экземпляра.
Интерфейсы являются легкими способом для обеспечения определенного поведения. Это один из способов думать о.
Пара других различий:
Абстрактные классы могут иметь статические методы, свойства, поля и т.д. и операторы, а интерфейсы - нет. Оператор Cast позволяет приводить к/от абстрактного класса, но не позволяет приводить к/от интерфейса.
Таким образом, в основном вы можете использовать абстрактный класс сам по себе, даже если он никогда не будет реализован (через его статические члены), а интерфейс вы не можете использовать сам по себе ни в коем случае.
Как насчет аналогии: когда я служил в ВВС, я пошел на обучение пилотов и стал пилотом ВВС США (ВВС США). В тот момент у меня не было квалификации летать на чем-либо, и мне пришлось пройти обучение по типам самолетов. После квалификации я был пилотом (абстрактный класс) и пилотом C-141 (конкретный класс). На одном из моих назначений мне дали дополнительную обязанность: Офицер безопасности. Теперь я был еще пилотом и пилотом С-141, но я также выполнял обязанности офицера безопасности (я внедрил, так сказать, ISafetyOfficer). От пилота не требовалось быть офицером безопасности, это могли делать и другие люди.
Все пилоты ВВС США должны следовать определенным правилам ВВС, и все пилоты C-141 (или F-16, или Т-38) «являются» пилотами ВВС США. Любой может быть офицером безопасности. Итак, резюмируем:
добавлено примечание: это должно было быть аналогией, чтобы помочь объяснить концепцию, а не рекомендация по кодировке. См. различные комментарии ниже, обсуждение интересное.