Почему в записях Java есть методы доступа вместо общедоступных полей final? [закрыто]
JEP-395 говорит
класс записи автоматически получает множество стандартных членов:
- Для каждого компонента в заголовке два члена: открытый метод доступа с тем же именем и возвращаемым типом, что и компонент, и закрытое конечное поле с тем же типом, что и компонент;
Если сгенерированное конечное поле имеет то же имя, что и метод доступа, почему вместо этого не создается общедоступное конечное поле?
4 ответа
Записи могут реализовывать интерфейсы, поэтому метод доступа к записи может быть реализацией метода интерфейса. Кроме того, использование средств доступа вместо прямого доступа к полю обеспечивает большую гибкость, например, вы можете заменить средство доступа, которое напрямую возвращает поле, на средство доступа, которое каким-то образом извлекает значение (или наоборот).
Записи также позволяют вам переопределить методы доступа, вместо того, чтобы просто возвращать поле, чтобы сделать что-то дополнительное. Использование в записях прямого доступа к полю ограничит и ограничит то, что вы можете делать с записями, и, таким образом, ограничит их полезность, в то время как наличие средств доступа предлагает вам базовый уровень, предлагаемый прямым доступом к полю, с возможностью делать больше, если необходимо.
Процитируем пример, приведенный Holger в комментариях:
классы
и предоставлять один и тот же API независимо от их внутреннего представления.
Короче говоря, создание аксессуаров для полей предлагает большую гибкость и возможности, чем прямой доступ к полю. То же самое относится и к простым неизменяемым классам.
Я думаю, что ключевым фактором в этом решении было то, что теперь у вас есть возможность переопределить методы получения записи:
public record MyRecord(String myProperty) {
@Override
public String myProperty() {
return "The property is " + myProperty;
}
}
Что-то подобное было бы невозможно с общедоступными конечными полями.
Обычно рекомендуется использовать методы доступа вместо прямого доступа к полю. Даже с записями имеет смысл продолжить эту практику, чтобы, например, можно было переименовывать поля без нарушения существующего кода.
Java-программисты абсолютно зависимы от ненужных инкапсуляторов. Они смотрят на публичное финальное поле и содрогаются в суеверном отвращении. Таким образом, мы получаем людей, делающих сумасшедшие рефлекторные заявления типа «Нет смысла в доступе к вашим полям напрямую (основной принцип программирования — инкапсуляция)», вместе с безумными рассуждениями о том, что разумно предписывать соглашение об именах (get/set и причудливо is) как единственный правильный способ обращения к данным, несмотря на то, что вы понятия не имеете, что на самом деле делают эти реализации методов.
Конечно, причина, по которой он сохраняется, заключается в непонятном решении языка не реализовывать свойства как встроенную функцию языка (а-ля C#, Kotlin) в любой момент за последние 30 лет. Вместо этого потратить десятилетие на неоднократные безуспешные попытки модульности языка (практически неиспользуемая функция с тех пор, как она наконец появилась).
Внедрение Records было бы прекрасной возможностью правильно реализовать свойства раз и навсегда (в конце концов, это до смешного простое улучшение — реализовать его в проходе desugar компилятора, и это работа дня, я сделал это сам; еще пару дней, чтобы добавить поддержку прослушивателя свойств во все доступные поля). Но все же нет.
Итак, разглагольствование, вернемся к вопросу. Открытые конечные поля были бы более разумной реализацией с возможностью сделать поле закрытым (
Но это противоречило бы (ошибочному) предубеждению против публичных конечных полей, которое характерно для сообщества Java.