Инкапсуляция. То есть скрывая реализацию данных вашего класса. Это позволяет вам изменить его позже, не нарушая весь клиентский код. Например. если у вас есть
class MyClass {
public int foo;
}
ваши клиенты могут написать код вроде
MyClass bar = new MyClass();
bar.foo++;
Теперь, если вы понимаете, что foo
должно быть на самом деле двойным, а не целым, вы измените его:
class MyClass {
public double foo;
}
и клиентский код не компилируется: - (
При хорошо спроектированном интерфейсе изменение внутренних элементов (частных частей) может даже включать преобразование переменной-члена в вычисление или наоборот:
class Person {
public String getName();
public String getStreetAddress();
public String getZipCode();
public String getCountryCode();
public int hashCode();
}
(используя свойства String ради простоты - в реальном мире некоторые из них, вероятно, заслуживают того, чтобы иметь свой собственный тип.)
С этим дизайном вы можете, например, бесплатно. введите внутреннее свойство Address
, которое будет содержать уличный адрес, почтовый индекс и код страны, и перезапишите ваши методы доступа, чтобы вместо этого использовать поля этого закрытого члена, чтобы ваши клиенты ничего не замечали.
Вы также можете свободно решать, вычислять ли каждый раз хэш-код или кэшировать его в частную переменную для повышения производительности. Однако, если это поле кэша было общедоступным, любой мог бы изменить его, что могло бы испортить поведение карты хеша и привести к незначительным ошибкам. Таким образом, инкапсуляция является ключом в обеспечении согласованности внутреннего состояния вашего объекта. Например. в приведенном выше примере ваши установщики могут легко проверить почтовый индекс и код страны, чтобы предотвратить установку недопустимых значений. Вы даже можете убедиться, что формат почтового индекса действителен для фактической страны, то есть обеспечить критерии допустимости, охватывающие несколько свойств. Благодаря хорошо спроектированному интерфейсу вы можете применить это связывание, например, предоставление только установщика для одновременной установки обоих свойств:
public void setCountryCodeAndZip(String countryCode, String zipCode);
Однако с открытыми полями у вас просто нет этих вариантов.
Особый вариант использования частных полей - неизменяемые объекты; это очень распространено, например, Java, примеры String
и BigDecimal
. Эти классы вообще не имеют открытых сеттеров, что гарантирует, что их объекты, однажды созданные, не изменят свое состояние. Это позволяет оптимизировать производительность, а также облегчает их использование, например, многопоточные программы, ORM и т. д.