#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. Лучше рассмотрите альтернативный объектно-ориентированный дизайн, четко распределяющий обязанности между объектами.
Рассмотрим принцип подстановки Лискова перед созданием подкласса.