Не секрет, что в Java существует соглашение о свойствах: для доступа к приватным полям класса нужно сделать соответствующие get/set методы. Многие начинающие java программисты часто недоумевают, какой в этом смысл, ведь почти всегда эти методы не делают ничего иного, кроме доступа к этим полям. А поскольку эти методы являются public
и доступны из любого кода, даже за пределами пакета, так почему бы просто не сделать поля публичными и напрямую назначать и читать их значения?
Рассмотрим данный случай на конкретном примере:
public class City { public String name; } City city = new City(); city.name = "Moscow"; System.out.println(city.name);
public class Country { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } Country country = new Country(); country.setName("Russia"); System.out.println(country.getName());
Главное отличие между публичными полями и методами доступа в том, что последние позволяют управлять доступом к свойству. Если поле будет доступно напрямую, вызывающий код может назначать ему любые значения, вероятно, не предусмотренные разработчиком класса. Например, полю может быть назначено значение null
, и если в другом участке кода нет соответствующей обработки, выполнение приведет к NullPointerException
.
Но если предусмотреть методы доступа к полю, а само поле пометить как private
, то можно контролировать этот процесс, поскольку теперь доступ может быть исключительно через предоставленные методы и никак иначе. В таком случае в set методах можно делать дополнительную валидацию и принимать решения, нужно ли в действительности назначать полю переданное значение или сделать дополнительное преобразование. То же самое относится и к get методам, где, например, можно вместо непосредственной ссылки на поле, клонировать и возвращать его копию:
public class Country { private String name; private City capital; public String getName() { return name; } public void setName(String name) { if(name != null) this.name = name; else this.name = ""; } public City getCapital() { if(capital != null) return capital.clone(); else return null; } public void setCapital(City capital) { this.capital = capital; } }
Однако, читатель может все же задаться вопросом: хорошо, там, где нужно, сделаем эти методы, а где мы не собираемся вводить валидацию, может быть тогда игра не стоит свеч, и можно просто обойтись public
полями?
На это можно ответить так. Используя эти методы, мы заранее предоставляем безопасный интерфейс доступа к данным класса, оставляя возможность внесения валидации, если вдруг выяснится, что что-то пошло не так. При этом весь остальной код, который будет использовать эти данные, не потребует переписывания. И даже если вы являетесь поклонником концепции YAGNI, то должен заметить, что это не тот случай. YAGNI пропагандирует отказ от чрезмерного усложнения кода в случаях, когда разработчик, решая конкретную задачу, мыслит слишком общими категориями и реализует настолько абстрактными код, который скорее всего никогда не будет использован повторно. В данном же случае мы просто используем устоявшееся соглашение java beans, которое, к тому же дает дополнительные удобства при использовании классов в сторонних библиотеках.
Свежие комментарии