Например, используете ли вы средства доступа и мутаторы в определениях своих методов или просто обращаетесь к данным напрямую? Иногда, все время или когда в Риме?
Инкапсуляция в определениях классов
Ответы (5)
Всегда старайтесь использовать аксессоры, даже внутри класса. Единственный случай, когда вы захотите получить доступ к состоянию напрямую, а не через общедоступный интерфейс, - это если по какой-то причине вам нужно обойти проверку или другую логику, содержащуюся в методе доступа.
Теперь, если вы окажетесь в ситуации, когда вам действительно нужно обойти эту логику, вам следует сделать шаг назад и спросить себя, указывает ли эта необходимость на изъян в вашем дизайне.
Изменить: прочтите Автоматические и явные свойства Эрика Липперта, в котором он углубляется в эту самую проблему и очень ясно объясняет вещи. Речь идет конкретно о C #, но теория ООП универсальна и прочна.
Вот отрывок:
Если причиной перехода от автоматически реализуемого свойства к явно реализованному свойству было изменение семантики свойства, то вам следует оценить, идентична ли желаемая семантика при доступе к свойству изнутри класса или отличается от желаемой семантики при доступе. собственность извне класса.
Если результатом этого исследования является «изнутри класса, желаемая семантика доступа к этому свойству отличается от желаемой семантики доступа к свойству извне», то ваше редактирование внесло ошибку. Вы должны исправить ошибку. Если они совпадают, значит, ваше редактирование не привело к ошибке; оставьте реализацию такой же.
В общем, предпочитаю аксессоры / мутаторы. Таким образом, я могу изменить внутреннюю реализацию класса, в то время как класс функционирует таким же образом для внешнего пользователя (или уже существующего кода, который я не хочу нарушать).
Аксессоры разработаны таким образом, что вы можете добавлять логику, зависящую от свойства. Такие как
int Degrees
{
set
{
_degrees = value % 360;
}
}
Итак, вы всегда хотели бы получить доступ к этому полю через геттер и сеттер, и таким образом вы всегда можете быть уверены, что значение никогда не будет больше 360.
Если, как упомянул Эндрю, вам нужно пропустить проверку, то вполне возможно, что есть недостаток в дизайне функции или в дизайне валидации.
Аксессоры и мутаторы предназначены для обеспечения согласованности ваших данных, поэтому даже внутри вашего класса вы всегда должны стремиться к тому, чтобы не было возможности ввести непроверенные данные в эти поля.
ИЗМЕНИТЬ
См. Также этот вопрос: Дизайн OO: Do вы используете общедоступные свойства или частные поля внутри компании?
Я не склонен делиться с внешним миром «внутренностями» моих классов, поэтому мои внутренние потребности в данных (материал частных методов), как правило, не соответствуют тому же типу вещей, что и мой открытый интерфейс.
Довольно редко я пишу аксессор / мутатор, который будет вызывать частный метод, но я подозреваю, что здесь меня меньшинство. Возможно, мне следует заняться этим больше, но я не склонен.
В общем, это мои [покрытые патиной] два цента.
Я часто начинаю с частных авто свойств, а затем при необходимости рефакторирую. Я проведу рефакторинг до свойства с резервным полем, а затем заменю резервное поле на «реальное» хранилище, например Session или ViewState для приложения ASP.NET.
От:
private int[] Property { get; set; }
to
private int[] _property;
private int[] Property
{
get { return _property; }
set { _property = value; }
}
to
private int[] _property;
private int[] Property
{
get
{
if (_property == null)
{
_property = new int[8];
}
return _property;
}
set { _property = value; }
}
to
private int[] Property
{
get
{
if (ViewState["PropertyKey"] == null)
{
ViewState["PropertyKey"] = new int[8];
}
return (int[]) ViewState["PropertyKey"];
}
set { ViewState["PropertyKey"] = value; }
}
Конечно, я использую ReSharper, поэтому на это уходит меньше времени, чем на публикацию сообщений.