Решая задачи, я столкнулся с неожиданным поведением геттеров. В здешних лекциях и даже в генерируемых IntelliJ IDEA геттерах используется простейшая схема:
public final class A {
private A field;
public A getField() {
return field;
}
public void setField(A field) {
this.field = field;
}
}
Если поле примитивного типа или String, которые передаются по значению, то всё в порядке, но если объект передаётся по ссылке, то получается, что через геттер можно получить полный доступ к полю, что сводит на нет установленный уровень доступа protected.
Если в сеттере стоит какое-либо условие валидности, то через такой геттер его можно обойти, что нарушает инкапсуляцию и правильно было бы создавать клон объекта, что бы избежать этой неприятности.
Понимаю, что не все объекты просто клонировать и если это отдаётся на ответственность программиста, то странно почему об этом нигде в лекциях не встречалось упоминаний.
UPD:
Геттер, как идея, конечно же, не нарушает инкапсуляцию, но написан он должен быть так, что бы не предать принципов ООП. Это значит, что если геттер выдаёт объект, то таким образом, что бы пользователь не смог его изменить никаким другим способом, который прописан в классе.
В классе Collections существует замечательный метод public static Collection unmodifiableCollection(Collection c)
который выдаёт read-only коллекцию.
Это накладывает ряд других ограничений, например, невозможность сортировки, но на этот случай в этом классе есть:
unmodifiableSortedSet
unmodifiableSortedMap
и ещё несколько, для большего удобства.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Вы получаете геттером ссылку на экземпляр класса А. Класс А тоже имеет внутреннюю структуру, разные модификаторы доступа… Скажем, доступа к приватным полям класса А вы не получаете через геттер. Все норм… Геттер просто возвращает ссылку на значение в поле А… Что не так? В чем противоречие?
Если бы всё было в А скрыто — то какой толк в такой ссылке? Как с ней работать?