Вопрос

Сегодня я прочитал книгу, и автор написал, что в хорошо продуманном классе единственный способ получить доступ к атрибутам-это один из методов этого класса. Это широко распространенная мысль? Почему так важно инкапсулировать атрибуты? Каковы могут быть последствия этого не делать? Я читал где -то раньше, что это улучшает безопасность или что -то в этом роде. Любой пример в PHP или Java был бы очень полезным.

Это было полезно?

Решение

Это широко распространенная мысль?

В объектно-ориентированном мире, да.

Почему так важно инкапсулировать атрибуты? Каковы могут быть последствия этого не делать?

Объекты предназначены для того, чтобы быть сплоченными объектами, содержащими данные и поведение, к которым другие объекты могут получить доступ к контролируемому пути через общественный интерфейс. Если класс не инкапсуляет свои данные и поведение, он больше не контролирует доступ к данным и не может выполнять свои контракты с другими объектами, подразумеваемыми публичным интерфейсом.

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

Любой пример в PHP или Java был бы очень полезным.

Вот пример Java:

public class MyClass {
    // Should not be < 0
    public int importantValue;
    ...
    public void setImportantValue(int newValue) {
        if (newValue < 0) {
           throw new IllegalArgumentException("value cannot be < 0");
        }
    }
    ...
}

Проблема здесь в том, что я не инкапсулировал importantValue Сделав это private Вместо публики, любой может прийти и обойти чек, который я поместил в сеттере, чтобы предотвратить недопустимое состояние объекта. importantValue никогда не должно быть меньше 0, но отсутствие инкапсуляции делает невозможным, чтобы она не была таковой.

Другие советы

Каковы могут быть последствия этого не делать?

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

Разрешено ли их привязывать прямой доступ к атрибутам, у которых нет никаких правил (например, все, что подходит в целом, в порядке), является хорошей практикой, является спорной. Я полагаю, что использование Getters и Setters - хорошая идея ради последовательности, то есть вы всегда знаете, что можете позвонить setFoo() Чтобы изменить foo Атрибут без необходимости смотреть, можете ли вы сделать это напрямую. Они также позволяют вам защищать в будущем ваш класс, чтобы, если у вас есть дополнительный код для выполнения, место для его помесщения уже там.

Лично я думаю, что необходимость использования Getters и Setters-неуклюже. Я бы предпочел написать x.foo = 34 чем x.setFoo(34) И с нетерпением ждем того дня, когда какой -то язык придумает эквивалент триггеров базы данных для участников, которые позволяют вам определять код, который стреляет до, после или вместо заданий.

Мнения о том, как достигается «хороший ood», - это десять центов, а также очень опытные программисты и дизайнеры, как правило, не согласны с выбором дизайна и философией. Это может быть фонарь пламени, если вы спросите людей по широкому разнообразию языкового фона и парадигм.

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

Позвольте мне добавить это: это зависит. Инкапсуляция (на языке поддерживающих) дает вам некоторый контроль над тем, как используются ваши классы, так что вы Можно Скажите людям: это API, и вы должны использовать это. На других языках (например, Python) разница между официальными API и неформальными (с учетом изменений) интерфейсов заключается только в том, чтобы только называть конвенцию (только соглашение (только для именования (только соглашение об именах (В конце концов, мы все согласны с взрослыми здесь)

Инкапсуляция не является функцией безопасности.

Еще одна мысль, чтобы задуматься

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

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

Если все используют методы доступа в своем коде, это становится почти тривиальным для реализации. Что -то вроде так:

Myapi версия 1.0

public class MyClass {
    private int importantValue;
    ...
    public void setImportantValue(int newValue) {
        if (newValue < 0) {
           throw new IllegalArgumentException("value cannot be < 0");
        }
        importantValue = newValue;
    }
    ...
}



Myapi v1.1 (теперь с аудиторскими тропами)

public class MyClass {
    private int importantValue;
    ...
    public void setImportantValue(int newValue) {
        if (newValue < 0) {
           throw new IllegalArgumentException("value cannot be < 0");
        }
        this.addAuditTrail("importantValue", importantValue, newValue);
        importantValue = newValue;
    }
    ...
}

Существующие пользователи API не вносят никаких изменений в свой код, и теперь доступна новая функция (Audit Trail).
Без инкапсуляции, используя аксессов, вы столкнулись с огромными усилиями по миграции.


При первом кодировании это будет казаться большой работой. Это гораздо быстрее напечатать: class.varName = something против class.setVarName(something); Но если все выбрали легкий выход, то получив оплату за запрос на функцию BigCustomera, это было бы огромным усилием.

В Программирование объекта Существует принцип, который известен как (http://en.wikipedia.org/wiki/open/closed_principle): poc -> Принцип открытого и закрытого. Анкет Этот принцип остается для: Следует открыть дизайн класса хорошо для расширения (наследование), но закрыт для модификации внутренних элементов (инкапсуляция). Анкет Это означает, что вы не сможете изменить состояние объекта, не заботясь об этом.

Таким образом, новые языки изменяют только внутренние переменные (поля) через свойства (методы Getters и Setters в C ++ или Java). В C# свойства компилируют методы в MSIL.

C#:

int _myproperty = 0;
public int MyProperty
{
    get { return _myproperty; }
    set { if (_someVarieble = someConstantValue) { _myproperty = value; } else { _myproperty = _someOtherValue; }  }    
}

C ++/java:

int _myproperty = 0;
public void setMyProperty(int value) 
{
  if (value = someConstantValue) { _myproperty = value; } else { _myproperty = _someOtherValue; }
}
public int getMyProperty() 
{
    return _myproperty;
}

Возьмите эти идеи (из Голова первой c#):

  • Подумайте о том, как поля могут неправильно использовать. Что может пойти не так, если они не установлены должным образом.
  • Все ли в вашем классе публично? Потратьте некоторое время на размышления о инкапсуляции.
  • Какие поля требуют обработки или расчета? Они являются главными кандидатами.
  • Расставьте поля и методы публично, если вам нужно. Если у вас нет причин, чтобы объявить что -то публичное, нет.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top