Как в Java скрыть даже от разработчика поле, доступ к которому должен осуществляться с помощью геттера и/или сеттера
Много написано о том, что хорошей практикой является объявление полей экземпляра класса с модификатором private
, а чтение и модификацию их осуществлять с помощью public
геттера и/или сеттера. Действительно, этот приём даёт уверенность, что вся логика, предусмотренная разработчиком для событий чтения/записи, будет выполнена в случае использования класса кем-либо. Однако, разработчик класса в методах по-прежнему имеет возможность читать и записывать значение поля напрямую! Чтобы избежать этого, предлагаю следующий трюк. Потребуется чуть больше кода, но теперь даже IDE не сможет подсовывать это поле в подсказках.
Для каждого "super private
" поля нам потребуется интерфейс расширяющий Supplier
и Consumer
и объект анонимного класса, реализующего этот интерфейс, в который мы помещаем поле value. Вся логика геттера и сеттера происходит в этом классе. Сами геттер и сеттер - лишь обёртки для public
доступа.
Всё понятно из примера ниже.
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* Пример использования "super private" поля value, доступ к которому
* возможен только через геттер и сеттер даже из методов самого класса
*/
public class GetterSetter {
interface SupplierConsumer<T> extends Supplier<T>, Consumer<T> {}
/**
* объект анонимного класса имплементирущего SupplierConsumer,
* содержащий поле value.
* Используется в обёртке сеттера setValue(...) и геттера getValue()
*/
private final SupplierConsumer<String> get_set_value =
new SupplierConsumer<>() {
/**
* Само поле value
*/
String value;
/**
* Реализация интерфейса Supplier
* @return - значение поля value
*/
@Override
public String get() {
return value;
}
/**
* Реализация интерфейса Consumer
* @param another_value - новое значение для поля value
*/
@Override
public void accept(String another_value) {
/*
Здесь можно выполнить нужные проверки и другие действия
*/
value = another_value;
}
};
/**
* Геттер для поля value
* @return значение поля value
*/
public String getValue() {
return get_set_value.get();
}
/**
* Сеттер для поля value
* @param value - новое значение для поля value
*/
public void setValue(String value) {
get_set_value.accept(value);
}
static public void main(String[] args) {
GetterSetter gs = new GetterSetter();
System.out.println(gs.getValue());
gs.setValue("Здравствуй, мир!");
System.out.println(gs.getValue());
}
}
Запуск класса выводит, как и ожидалось:
"java.exe" GetterSetter
null
Здравствуй, мир!