Java: интерфейс против абстрактного класса (относительно полей)

Из того, что я собрал, я хочу заставить класс использовать определенные частные поля (и методы). Мне нужен абстрактный класс, потому что интерфейс объявляет только общедоступные / статические / конечные поля и методы. Верный??

Я только что начал свой первый большой java-проект и хочу убедиться, что не собираюсь навредить себе позже :)

за исключением последних полей / методов в интерфейсе, это было бы правильно.

Matthew Brubaker 20.01.2009 20:26
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
10
1
15 255
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

Это правильно. Но это не обязательно решение либо-либо, вы можете объединить преимущества интерфейсов и абстрактных классов, предоставив скелетную реализацию вместе с вашим интерфейсом. Вы можете найти очень интересное описание этого подхода в Эффективная Java, 2-е изд., пункт 18 («Предпочитайте интерфейсы абстрактным классам»).

Частные поля и методы не могут использоваться подклассами (кроме случаев, когда они также являются внутренними классами). Однако вы можете сделать их защищенными.

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

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

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

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

Steven A. Lowe 20.01.2009 21:12

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

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

Даже если вы унаследованы от абстрактного класса, вы не сможете получить доступ к его частным полям / методам.

Интерфейсы определяют договор для поведения. Они должны быть об этом, а не об атрибутах.

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

Ответ принят как подходящий

Довольно часто предоставляется и то, и другое, так что в итоге вы получите:

public interface Sendable {
    public void sendMe();
}

а также

public abstract class AbstractSender implements Sendable {
    public abstract void send();

    public void sendMe() {
        send(this.toString());
    }
}

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

разве вы не хотите, чтобы AbstractSender реализует Sendable.

Milhous 20.01.2009 21:40

Да. Исправлено. На самом деле, я хочу менее надуманный пример, но сразу ничего не пришло в голову.

Richard Campbell 20.01.2009 22:23
docs.oracle.com/javase/tutorial/java/IandI/abstract.html - «Если класс включает абстрактные методы, сам класс должен быть объявлен абстрактным». Ваш код действительно компилируется?
cdunn2001 16.03.2012 03:50
I want to force a class to use particular private fields (and methods)

Эта часть вашего вопроса вызывает сомнения: как вы думаете, почему вы хотите это сделать?

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

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

    public abstract class A {

      protected Object thing;
    }

может быть доступен другому классу в том же пакете (может расширять класс A или нет)

A a = new A();
a.thing.toString();

На самом деле это не «принуждение» другого класса к его использованию, а скорее «включение».

Другие вопросы по теме