Самый эффективный подход в унаследованных полях?

#java

#java

Вопрос:

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

     R
    |
 .-- -- ------.
 |     |  ... |
S1     S2 ... Sn
  

Класс R имеет поле x определенного типа, скажем X , которое не является простым типом, который должен наследовать каждый подкласс. Подклассы могут выполнять виды внутренней обработки поля x , а также предоставлять его как свойство.
Возникла своего рода дискуссия о том, какой из этих двух стилей кодирования предпочтительнее:

1-е решение

Нужно R объявить x класс как частное поле и предоставить общедоступные средства получения и установки

 class R {
    ....
    private X x;

    ....

    public X getX() { ... }
    public void setX(X ax) { ... }
}
  

2-е решение

Есть ли класс, R объявленный x как защищенное поле

Какой из них, по вашему мнению, может быть предпочтительным решением?

Комментарии:

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

2. Эта иерархия представляет собой иерархию обратных бинов, в которую я переместил весь общий / шаблонный код в базовом классе (R). Каждый подкласс является обратным значением, относящимся к различным страницам jsf.

Ответ №1:

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

Все зависит от доступа, который вы хотите, чтобы к нему имели другие классы.

Редактировать: (первое решение)

Ответ №2:

Это зависит от того, что вы хотите разрешить делать с внутренним X. Если вы хотите, чтобы это было доступно / изменяемо извне, сделайте общедоступным get / set. Но если вы хотите, чтобы они могли изменяться только его подклассами, тогда используйте protected и все. ИМХО

Комментарии:

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

2. @Adriaan Koster очень хороший комментарий. Если переменные должны быть «полностью» доступны для подклассов, тогда у вас должен быть прямой доступ к ним, они должны быть защищены, нет необходимости в методах. Но тогда, если вы создаете API или вы не полностью уверены в дизайне класса, таким образом, чтобы защитить свой код от будущих изменений, выполнение того, что вы говорите, было бы лучшим вариантом. Здесь возникает множество проблем, например, «более быстрый» прямой доступ в сравнении с возможностью модификации кода. В конце концов, я полагаю, все зависит от того, как используется родительский класс.

Ответ №3:

Если вам нужно использовать наследование, это самый безопасный способ:

 class R
{
  private X x;

  protected X getX()
  {
    return this.x;
  }
}
  

Почему бы не иметь R в качестве отдельного класса и ссылаться на него из S1, S2, ... Sn ?

Ответ №4:

Предпочтительнее частное поле. Однако вам в любом случае не следует изменять внутреннее состояние другого объекта из другого класса, даже если это подкласс.

Звучит так, как будто вы вставляете огромную связь между R, S1, S2 и т.д. И X. Лучше рассмотрите альтернативный объектно-ориентированный дизайн, четко распределяющий обязанности между объектами.

Рассмотрим принцип подстановки Лискова перед созданием подкласса.