Должен ли я использовать абстрактный метод или переменную экземпляра для данных, которые должны быть указаны подклассом? - PullRequest
5 голосов
/ 01 февраля 2011

Я пишу абстрактный класс, и у меня есть переменная, которая должна быть определена подклассом (в данном случае это int, который используется в суперклассе).Я не могу решить, следует ли определять переменную protected со значением по умолчанию и позволить подклассу изменять значение либо в конструкторе, либо с помощью метода setter.Или определить абстрактный метод в родительском классе так, чтобы все подклассы должны были реализовать его и возвращать значение, которое они хотят использовать (затем получить доступ к методу в суперклассе, используя абстрактный метод).Может кто-нибудь сказать мне, если есть какие-либо веские причины, по которым один из способов предпочтительнее другого?

Абстрактный метод:

public abstract int getValue();

public int getValue() {
    return 5;
}
  • Плюсы:

Заставляет подкласс думать об этом значении и выбирать, каким оно должно быть.

  • Минусы:

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

Защищенная переменная:

protected int value;

public SubClassImpl() {
    value = 5;
}
  • Плюсы:

Может определять значение по умолчанию, а подклассы могут просто игнорировать его, если им все равно.

  • Минусы:

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

Ответы [ 2 ]

8 голосов
/ 01 февраля 2011

Ну, это зависит ...

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

  • Может быть у подклассов есть причина для вычисления переменной на основе другого изменяемого состояния? Если это так, подойдет абстрактный получатель.

  • В противном случае, я бы, вероятно, использовал приватную переменную и защищенный установщик. Я вообще не фанат не приватных переменных. Это может позволить вам реагировать на изменения значения в вашем базовом классе, такие как изменение других полей компьютера. Чтобы избежать присутствия значения по умолчанию, вы можете объединить его с параметром конструктора, чтобы принудительно установить начальное значение, которое подкласс может изменить позже через установщик.

0 голосов
/ 01 февраля 2011

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

Например, в Guava это позволяет ForwardingSortedMap расширять ForwardingMap .

...