Введение

В информатике метод-мутатор — это метод, используемый для управления изменениями переменной. Они также широко известны как методы-сеттеры. Часто сеттер сопровождается геттером, который возвращает значение приватной переменной-члена. Все вместе они также известны как методы доступа. Метод-мутатор наиболее часто используется в объектно-ориентированном программировании, в соответствии с принципом инкапсуляции. Согласно этому принципу, переменные-члены класса делаются приватными, чтобы скрыть и защитить их от другого кода, и могут быть изменены только через публичный метод-член (метод-мутатор), который принимает желаемое новое значение в качестве параметра, опционально выполняет его проверку и изменяет приватную переменную-член. Методы-мутаторы можно сравнить с перегрузкой оператора присваивания, но они обычно встречаются на разных уровнях объектной иерархии. Методы-мутаторы также могут использоваться и в не объектно-ориентированных средах. В этом случае мутатору передается ссылка на переменную, которую необходимо изменить, вместе с новым значением. В этом сценарии компилятор не может предотвратить обход метода-мутатора и прямое изменение переменной. Ответственность за то, чтобы переменная изменялась только через метод-мутатор, а не напрямую, ложится на разработчиков. В языках программирования, которые их поддерживают, свойства предлагают удобную альтернативу, не отказываясь от преимуществ инкапсуляции. В приведенных ниже примерах полностью реализованный метод-мутатор также может проверять входные данные или выполнять другие действия, например, вызывать событие.

Последствия

Альтернатива определению методов мутатора и аксессора, или блоков свойств, заключается в предоставлении переменной экземпляра видимости, отличной от приватной, и доступе к ней напрямую извне объектов. Мутаторы и аксессоры позволяют реализовать гораздо более тонкий контроль над правами доступа. Например, параметр можно сделать доступным только для чтения, определив только аксессор, но не мутатор. Видимость этих двух методов может различаться: часто бывает полезно, чтобы аксессор был публичным, а мутатор оставался защищенным, доступным только в пределах пакета или внутренним. Блок, в котором определяется мутатор, предоставляет возможность для проверки или предварительной обработки входящих данных. Если весь внешний доступ гарантированно осуществляется через мутатор, то эти шаги нельзя будет пропустить. Например, если дата представлена отдельными приватными переменными год, месяц и день, то входящие даты могут быть разделены мутатором `setDate`, а для обеспечения согласованности к тем же приватным переменным экземпляра обращаются методы `setYear` и `setMonth`. Во всех случаях значения месяца, выходящие за пределы 1–12, могут быть отклонены одним и тем же кодом. Аксессоры, напротив, позволяют синтезировать полезные представления данных из внутренних переменных, сохраняя при этом их структуру инкапсулированной и скрытой от внешних модулей. Аксессор `getAmount` для денежных значений может создавать строку из числовой переменной, при этом количество десятичных знаков определяется скрытым параметром валюты. Современные языки программирования часто предлагают возможность генерировать шаблонный код для мутаторов и аксессоров в одну строку, например, `public string Name { get; set; }` в C# и `attr_accessor :name` в Ruby. В этих случаях блоки кода для валидации, предварительной обработки или синтеза не создаются. Эти упрощенные аксессоры по-прежнему сохраняют преимущество инкапсуляции по сравнению с простыми публичными переменными экземпляра, но часто, по мере развития архитектуры системы, когда программное обеспечение поддерживается и требования меняются, требования к данным становятся более сложными. Многие автоматически созданные мутаторы и аксессоры в конечном итоге заменяются отдельными блоками кода. Преимущество автоматического создания их на ранних этапах реализации заключается в том, что публичный интерфейс класса остается неизменным, независимо от того, добавляется ли более сложная логика, что избавляет от необходимости масштабного рефакторинга. Работа с параметрами, имеющими мутаторы и аксессоры, внутри класса, где они определены, часто требует дополнительного внимания. На ранних этапах реализации, когда в этих блоках содержится мало или совсем нет дополнительного кода, не имеет значения, осуществляется ли прямой доступ к приватной переменной экземпляра или нет. Однако по мере добавления валидации, перекрестной валидации, проверок целостности данных, предварительной обработки или других усложнений могут возникать скрытые ошибки, когда некоторый внутренний доступ использует новый код, а в других местах он обходит его. Функции-аксессоры могут быть менее эффективными, чем прямое получение или сохранение полей данных из-за дополнительных шагов, но такие функции часто оптимизируются путем встраивания, что устраняет накладные расходы на вызов функции.