Собственность и Инкапсуляция
Ниже приведен вопрос об использовании свойств в классе.
Я использовал открытые свойства вместо того, чтобы выставлять переменные-члены публично. Большинство советуют, что этот подход помогает инкапсуляции. Однако я не понимаю преимущества инкапсуляции, сделав его свойством.
Многие люди не знают истинную причину использования свойств. Они просто делают это как часть стандарта кодирования.
Может кто-то ясно объяснить, как свойство лучше, чем общедоступная переменная-член, и как оно улучшает инкапсуляцию?
4 ответа
Инкапсуляция помогает, изолируя классы вызовов от изменений.
Давайте представим, что у вас есть простой класс, который моделирует автомобильный двигатель (потому что все примеры ОО должны включать автомобильную аналогию:)). У вас может быть простое поле, подобное этому:
private bool engineRunning;
Просто сделав это поле общедоступным или предоставив метод получения IsEngineRunning(), это не выглядит иначе.
Теперь предположим, что вы делаете свой класс более сложным, вы хотите удалить это поле и заменить его следующим:
private bool ignitionOn;
private bool starterWasActivated;
Теперь, если у вас есть много классов, обращающихся к старому engineRunning
поле вы должны пойти и изменить их все (плохие времена).
Если вместо этого вы начали с:
public bool IsEngineRunning()
{
return this.engineRunning;
}
Теперь вы можете изменить его на:
public bool IsEngineRunning()
{
return ignitionOn && starterWasActivated;
}
и интерфейс класса остается прежним (хорошие времена).
Лучше предоставлять свойства вместо переменных-членов, потому что это позволит вам выполнять все виды проверок при установке или получении значения переменной-члена.
Предположим, у вас есть переменная-член:
private int id;
и у вас есть государственная собственность
public int ID
{
get
{
// do something before returning
}
set
{
// do some checking here may be limits or other kind of checking
}
}
Я сделаю это коротким. Свойства = гибкость
1 Свойства полезны для создания членов, которые вы не хотите постоянно хранить в классе или которые являются совокупностями / функциями существующих членов.
Например. возраст может быть выведен на основе даты рождения, canSwim может быть сгенерирован из hasLimbs && floats
2 Представление членов в качестве свойств может быть полезно при работе с неожиданными изменениями [кто-нибудь когда-либо прогнозировал все запросы клиента?] В системах с существующей базой данных.
Например. isAllowed имеет значение true, если пользователь старше 18 лет и кэшируется для повышения производительности. Клиент хочет запустить службу в США, и вы можете вернуть значение false, если установлено значение false, и проверять возраст, только если кэш имеет значение true.
Некоторые мысли:
Вы можете изменить внутреннее представление ваших данных, не затрагивая вызывающие классы.
Например (до)
public boolean isActive() { return this.is_active; }
(после)
public boolean isActive() { return this.is_active && this.approved && this.beforeDeadline; }
Это особенно важно, если ваш код используется другими (т.е. ваш код сторонний). В определенной степени ваш интерфейс /API должен оставаться стабильным. Небольшие изменения не должны влиять на код другого кода, который его использует.
Вы можете иметь более сложные операции. Рассмотрим переменную
is_active
, Возможно, изменение значения этой переменной также влияет на другие свойства объекта. Если вы инкапсулируете доступ в метод, вы можете позаботиться об этом внутри этого метода, и вызывающий не должен заботиться.Например
public void setActive(boolean active) { this.is_active = active; this.startTimeout(); this.updateOtherInformation(); }
Поэтому он обеспечивает выполнение определенной серии действий. Вы не должны полагаться на тот факт, что вызывающая сторона выполняет эти действия правильно. Ваш объект всегда будет в правильном состоянии.