Search
Write a publication
Pull to refresh

Как в 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
Здравствуй, мир!
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.