Когда использовать абстрактный класс или интерфейс?

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

Ответ 1

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

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

- EDIT - забыл упомянуть, Эрвиккер напомнил мне

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

Ответ 2

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

Ответ 3

Абстрактный класс - это класс, который не реализует некоторые из его методов. Очевидно, это невозможно создать. Вы должны наследовать от абстрактного класса и реализовывать абстрактные методы в другом классе.

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

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

Хорошим примером является коллекция framework библиотеки классов Java. У вас есть список интерфейсов, который определяет, как должны вести себя списки. Некоторые реализации - это, например, ArrayList и LinkedList. Поскольку они ведут себя одинаково, материал, который работает одинаково для обоих, реализован в абстрактном классе AbstactList, оба наследуют это.

Ответ 4

См. "Интерфейс" в основном "Контракт". Когда вы определяете интерфейс, вы определяете Контракт. Там, где расширены абстрактные классы, реализуются интерфейсы.

Рассмотрим пример.

public interface Friend {
void hello();
}

Теперь вы определили контракт, в котором говорится, что любой класс, который хочет реализовать Friend, должен предоставить определение метода hello().

Вот реализация:

public class myFriend implements Friend {
public void hello()
println("Done");
}

Теперь myFriend выполнил контракт. Теперь возникает вопрос: где должны использоваться интерфейсы?

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

Ответ 5

SamuelCarrijo, похоже, хорошо ответил на этот вопрос.

Кроме того, для Java для некоторых фреймворков требуется интерфейс для работы. Я думаю (скажем) динамические прокси или некоторые клиентские/серверные схемы проксирования. Это связано с тем, что они используют интроспекцию объекта для определения методов, реализуемых интерфейсами, реализуемыми объектом. Поэтому иногда вам нужно реализовать интерфейс для объекта, где, возможно, вы обычно не беспокоитесь.

Обратите внимание на эту причину для интерфейсов, характерных для Java.

Ответ 6

Абстрактные классы используются, когда вы строите иерархию наследования. Однако большинство иерархий наследования не должны быть слишком "глубокими" (т.е. Слишком много уровней наследования). Многие объектно-ориентированные книги по дизайну будут использовать интерфейсы над наследованием (одна книга, которую я прочитал однажды, процитировал разработчика, сказав, что "наследование - это самая крутая [объектно-ориентированная] функция, которую вы не будете реализовывать" ), поскольку это позволяет назначать классы поведением "по контракту", где контракт является интерфейсом.

Стоит отметить ответ samuelcarrijo - если вы хотите использовать реализацию метода по умолчанию, вам придется использовать абстрактный класс, который имеет конкретную реализацию метода, чтобы дать ему реализацию по умолчанию. Эта реализация по умолчанию может быть переопределена в дочерних классах.

Надеюсь, это поможет!