Инкапсуляция в определениях классов

Например, используете ли вы средства доступа и мутаторы в определениях своих методов или просто обращаетесь к данным напрямую? Иногда, все время или когда в Риме?


person Derek E    schedule 17.03.2009    source источник
comment
Я бы назвал это обманом: stackoverflow.com/questions/99688/   -  person Dana    schedule 17.03.2009
comment
Кажется, эта ветка говорит о классе, общающемся с внешним миром, я нет.   -  person Derek E    schedule 17.03.2009


Ответы (5)


Всегда старайтесь использовать аксессоры, даже внутри класса. Единственный случай, когда вы захотите получить доступ к состоянию напрямую, а не через общедоступный интерфейс, - это если по какой-то причине вам нужно обойти проверку или другую логику, содержащуюся в методе доступа.

Теперь, если вы окажетесь в ситуации, когда вам действительно нужно обойти эту логику, вам следует сделать шаг назад и спросить себя, указывает ли эта необходимость на изъян в вашем дизайне.

Изменить: прочтите Автоматические и явные свойства Эрика Липперта, в котором он углубляется в эту самую проблему и очень ясно объясняет вещи. Речь идет конкретно о C #, но теория ООП универсальна и прочна.

Вот отрывок:

Если причиной перехода от автоматически реализуемого свойства к явно реализованному свойству было изменение семантики свойства, то вам следует оценить, идентична ли желаемая семантика при доступе к свойству изнутри класса или отличается от желаемой семантики при доступе. собственность извне класса.

Если результатом этого исследования является «изнутри класса, желаемая семантика доступа к этому свойству отличается от желаемой семантики доступа к свойству извне», то ваше редактирование внесло ошибку. Вы должны исправить ошибку. Если они совпадают, значит, ваше редактирование не привело к ошибке; оставьте реализацию такой же.

person Andrew Hare    schedule 17.03.2009

В общем, предпочитаю аксессоры / мутаторы. Таким образом, я могу изменить внутреннюю реализацию класса, в то время как класс функционирует таким же образом для внешнего пользователя (или уже существующего кода, который я не хочу нарушать).

person Pete    schedule 17.03.2009

Аксессоры разработаны таким образом, что вы можете добавлять логику, зависящую от свойства. Такие как

int Degrees
{
    set
    {
        _degrees = value % 360;
    }
}

Итак, вы всегда хотели бы получить доступ к этому полю через геттер и сеттер, и таким образом вы всегда можете быть уверены, что значение никогда не будет больше 360.

Если, как упомянул Эндрю, вам нужно пропустить проверку, то вполне возможно, что есть недостаток в дизайне функции или в дизайне валидации.

Аксессоры и мутаторы предназначены для обеспечения согласованности ваших данных, поэтому даже внутри вашего класса вы всегда должны стремиться к тому, чтобы не было возможности ввести непроверенные данные в эти поля.

ИЗМЕНИТЬ

См. Также этот вопрос: Дизайн OO: Do вы используете общедоступные свойства или частные поля внутри компании?

person DevinB    schedule 17.03.2009

Я не склонен делиться с внешним миром «внутренностями» моих классов, поэтому мои внутренние потребности в данных (материал частных методов), как правило, не соответствуют тому же типу вещей, что и мой открытый интерфейс.

Довольно редко я пишу аксессор / мутатор, который будет вызывать частный метод, но я подозреваю, что здесь меня меньшинство. Возможно, мне следует заняться этим больше, но я не склонен.

В общем, это мои [покрытые патиной] два цента.

person itsmatt    schedule 17.03.2009

Я часто начинаю с частных авто свойств, а затем при необходимости рефакторирую. Я проведу рефакторинг до свойства с резервным полем, а затем заменю резервное поле на «реальное» хранилище, например 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, поэтому на это уходит меньше времени, чем на публикацию сообщений.

person John Saunders    schedule 17.03.2009