Jump to content

Метод мутатора

(Перенаправлено с Аксессора )

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

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

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

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

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

Подразумеваемое

[ редактировать ]

Альтернативой определению методов-мутаторов и средств доступа или блоков свойств является предоставление переменной экземпляра некоторой видимости, отличной от частной, и доступ к ней непосредственно извне объектов. Гораздо более тонкий контроль прав доступа можно определить с помощью мутаторов и аксессоров. Например, параметр можно сделать доступным только для чтения, просто определив метод доступа, а не мутатор. Видимость этих двух методов может быть разной; часто бывает полезно, чтобы метод доступа был общедоступным, в то время как мутатор оставался защищенным, частным для пакета или внутренним.

Блок , в котором определен мутатор, предоставляет возможность проверки или предварительной обработки входящих данных. Если весь внешний доступ гарантированно осуществляется через мутатор, то эти шаги невозможно обойти. Например, если дата представлена ​​отдельным приватным year, month и day переменные, то входящие даты можно разделить по setDate мутатор, в то время как для согласованности доступ к одним и тем же частным переменным экземпляра осуществляется setYear и setMonth. Во всех случаях значения месяца за пределами 1–12 могут быть отклонены одним и тем же кодом.

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

Современные языки программирования часто предлагают возможность генерировать шаблон для мутаторов и средств доступа в одной строке, как, например, в C#. public string Name { get; set; } и Руби attr_accessor :name. В этих случаях блоки кода для проверки, предварительной обработки или синтеза не создаются. Эти упрощенные методы доступа по-прежнему сохраняют преимущество инкапсуляции перед простыми общедоступными переменными экземпляра, но обычно по мере развития системы программное обеспечение поддерживается , а требования изменяются, а требования к данным становятся более сложными. Многие автоматические мутаторы и средства доступа со временем заменяются отдельными блоками кода. Преимущество автоматического создания их на первых этапах реализации заключается в том, что общедоступный интерфейс класса остается идентичным независимо от того, добавляется ли большая сложность или нет, и в этом случае не требуется обширного рефакторинга. [1]

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

Функции доступа могут быть менее эффективными, чем прямая выборка или сохранение полей данных, из-за дополнительных шагов, [2] однако такие функции часто являются встроенными , что устраняет накладные расходы на вызов функции.

 студента,                    структура      возраст           дд          ?  студент                     заканчивает 
                     .code  Student_get_age         процедуры        объект  :  DWORD                        mov         ebx  ,   object                        mov         eax  ,   Student.age  [  ebx  ]                        ret  Student_get_age         endp  Student_set_age         процедуры        объект  :  DWORD  ,   age  :  DWORD                        mov         ebx  ,   object                        mov         eax  ,   age                        mov         Student.age  [  ebx  ],   eax                        ret  Student_set_age         конечная точка 

В файле Student.h:

#ifndef _STUDENT_H  #define _STUDENT_H  struct   Student  ;   /* непрозрачная структура */  typedef   struct   Student   Student  ;  студент   *  Student_new  (  int   age  ,   char   *  name  );  void   Student_delete  (  студент   *  s  );  void   Student_set_age  (  студент   *  s  ,   int   age  );  int   Student_get_age  (  студент   *  s  );  char   *  Student_get_name  (  студент   *  s  );  #endif 

В файле Student.c:

#include   <stdlib.h>  #include   <string.h>  #include   "student.h"  struct   Student   {    int   age  ;    символ   *  имя  ;  };  студент   *  Student_new  (  int   age  ,   char   *  name  )   {    Student   *  s   =   Malloc  (  sizeof  (  студент  ));    s  ->  name   =   strdup  (  имя  );    с  ->  возраст   =   возраст  ;    вернуть   с  ;  }  void   Student_delete  (  студент   *  s  )   {    свободно  (  s  ->  имя  );    бесплатно  (  ы  );  }  void   Student_set_age  (  student   *  s  ,   int   age  )   {    s  ->  age   =   age  ;  }  int   Student_get_age  (  студент   *  s  )   {    return   s  ->  age  ;  }  char   *  Student_get_name  (  student   *  s  )   {    return   s  ->  name  ;  } 

В файле main.c:

#include   <stdio.h>  #include   "student.h"  int   main  (  void  )   {    Student   *  s   =   Student_new  (  19  ,   "Maurice"  );    char   *  name   =   Student_get_name  (  s  );    int   old_age   =   Student_get_age  (  s  );    printf  (  "Старость %s = %i  \n  "  ,   name  ,   old_age  );    Student_set_age  (  s  ,   21  );    int   new_age   =   Student_get_age  (  s  );    printf  (  "Новый возраст %s = %i  \n  "  ,   name  ,   new_age  );    студент_удалить  (  ы  );    вернуть   0  ;  } 

В файле Makefile:

все  :   выход  .  текст  ;  кот  $< out.txt  :   основной  ; ./$< > $@ главное  :   главное  .  о   студент  .  o  main.o Student.o  :   студент  .  ч  чистый  :   ;  $(  РМ  )  *.  о   вон  .  текстовый   основной 

В файле Student.h:

#ifndef STUDENT_H  #define STUDENT_H  #include   <string>  class   Student   {  public  :      Student  (  const   std  ::  string  &   name  );      const   std  ::  строка  и   имя  ()   const  ;      void   name  (  const   std  ::  string  &   name  );  частный  :      std  ::  строка   name_  ;  };  #endif 

В файле Student.cpp:

#include   "Student.h"  Student  ::  Student  (  const   std  ::  string  &   name  )   :   name_  (  name  )   {  }  const   std  ::  string  &   Student  ::  name  ()   const   {      return   name_  ;  }  void   Student  ::  name  (  const   std  ::  string  &   name  )   {      name_   =   name  ;  } 

Этот пример иллюстрирует идею C# о свойствах , которые представляют собой особый тип члена класса . В отличие от Java, явные методы не определены; общедоступное «свойство» содержит логику для обработки действий. Обратите внимание на использование встроенной (необъявленной) переменной. value.

публичный   класс   Student  {      частной   строки   имя  ;      /// <summary>      /// Получает или задает имя студента      /// </summary>      public   string   Name      {          get   {   return   name  ;   }          Установить   {   имя   =   значение  ;   }      }  } 

В более поздних версиях C# (.NET Framework 3.5 и выше) этот пример можно сократить следующим образом, без объявления частной переменной name.

публичный   класс   Student  {      public   string   Name   {   get  ;   набор  ;   }  } 

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

публичный   класс   Student  {      public   string   Name   {   get  ;   частный   набор  ;   }  } 

Общий Лисп

[ редактировать ]

В Common Lisp Object System спецификации слотов в определениях классов могут указывать любой из :reader, :writer и :accessor опции (даже несколько раз) для определения методов чтения, методов установки и методов доступа (метод чтения и соответствующий setf метод). [3] Слоты всегда доступны напрямую через их имена с использованием with-slots и slot-value, а параметры доступа к слоту определяют специализированные методы, использующие slot-value. [4]

Сам CLOS не имеет понятия свойств, хотя расширение протокола MetaObject определяет средства доступа к именам функций чтения и записи слота, включая те, которые генерируются с помощью :accessor вариант. [5]

В следующем примере показано определение класса учащихся с использованием этих параметров слотов и прямого доступа к слотам:

(  defclass   Student   ()    ((  name        :initarg   :name        :initform   ""   :accessor   имя-ученика  )   ; имя-ученика может быть установлено     (  дата рождения   :initarg   :дата рождения   :initform   0    :reader   дата-рождения студента  )     (  номер      :initarg   : число      :initform   0    :читатель   -номер-студента   :писатель   set-номер-студента  )))  ;; Пример метода получения вычисляемого свойства (это просто метод)  (  defmethod   Student-age   ((  self   Student  ))    (  -   (  get-universal-time  )   (  Student-birthdate   self  )))  ;; Пример прямого доступа к слотам в вычисляемом установщике свойств  (  defmethod   (  setf   Student-age  )   (  new-age   self  Student   )  )    (  with-slots   (  birthdate  )   self      (  setfbirthdate   (   (  -   (  get-universal-time  )   new-age  ))      нью-эйдж  ))  ;; Параметры доступа к слотам генерируют методы, что позволяет определять дальнейшие методы  (  defmethod   set-student-number   :before   (  new-number   (  self   Student  ))    ;; Вы также можете проверить, существует ли уже студент с новым номером.    (  check- введите   новое число   (  целое число   1   *  ))) 

D поддерживает синтаксис функций получения и установки. В версии 2 языка методы получения и установки класса/структуры должны иметь @property атрибут. [6] [7]

класс   Student   {      private   char  []   name_  ;      // Получатель      @property   char  []   name  ()   {          return   this  .  имя_  ;      }      // Setter      @property   char  []   name  (  char  []   name_in  )   {          return   this  .  имя_   =   имя_в  ;      }  } 

А Student экземпляр можно использовать следующим образом:

автоматический   студент   =   новый   студент  ;  студент  .  имя   =   «Дэвид»  ;             // тот же эффект, что и Student.name("David")  auto   Student_name   =   Student  .  имя  ;   // тот же эффект, что и Student.name() 

Это простой класс на языке Delphi, который иллюстрирует концепцию открытого свойства для доступа к частному полю.

 интерфейса тип    TStudent   =   класс    strict   Private      FName  :   строка  ;      процедура   SetName  (  const   Value  :   string  )  ;    public      /// <summary>      /// Получаем или устанавливаем имя студента.      /// </summary>      свойства   имя  :   строки   чтение   FName   запись   SetName  ;    конец  ;  // ...  реализации  процедура   TStudent  .  SetName  (  константное   значение  :   строка  )  ;  начать    FName   :=   Значение  ;  конец  ;  конец  . 

В этом примере простого класса, представляющего студента, в котором сохранено только имя, можно видеть, что переменной имя является частным, то есть видимым только из класса Student, а «установщик» и «получатель» являются общедоступными, а именно: getName()" и " setName(name)"методы.

публичный   класс   Student   {      частное   строки   имя  ;      public   String   getName  ()   {          возвращаемое   имя  ;      }          Public   void   setName  (  String   newName  )   {          name   =   newName  ;      }  } 

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

функция   Студент  (  имя  )   {    var   _name   =   имя  ;    этот  .  getName   =   функция  ()   {      return   _name  ;    };    этот  .  setName   =   функция  (  значение  )   {      _name   =   значение  ;    };  } 

Или (используя устаревший способ определения средств доступа в веб-браузерах): [8]

функция   Студент  (  имя  ) {      var   _name   =   имя  ;         этот  .  __defineGetter__  (  'name'  ,   function  ()   {          return   _name  ;      });         этот  .  __defineSetter__  (  'имя'  ,   функция  (  значение  )   {          _name   =   значение  ;      });  } 

Или (используя прототипы для наследования и синтаксис средств доступа ES6 ):

функция   Студент  (  имя  ) {      это  .  _имя   =   имя  ;  }  Студент  .  прототип   =   {      получить   имя  ()   {          вернуть   это  .  _имя  ;      },      установите   имя  (  значение  )   {          this  .  _имя   =   значение  ;      }  }; 

Или (без использования прототипов):

var   Student   =   {      получить   имя  ()   {          вернуть   это  .  _имя  ;      },      установите   имя  (  значение  )   {          this  .  _имя   =   значение  ;      }  }; 

Или (используя defineProperty):

функция   Студент  (  имя  ) {      это  .  _имя   =   имя  ;  }  Объект  .  defineProperty  (  Student.prototype  set  {  ,   'name'  ,   {      get  :   function  ()   {          return   this  .  _name  ;      },      :  function   (  value  )  )   this          .  _name  =   value   ;  }      }  ; 

ЭкшнСкрипт 3.0

[ редактировать ]
пакет  {      общественный   класс   Student      {          частное   var   _name   :   String  ; 		         публичная   функция   get   name  ()   :   String          {               return   _name  ;          }          общедоступных   функций   набора   Имя  (  значение   :   String  )   :   void          {              _name   =   value  ;          }      }  } 

Использование традиционного синтаксиса Objective-C 1.0 с ручным подсчетом ссылок, как в GNUstep в Ubuntu 12.04 :

@interface   Студент  :  NSObject  {      NSString   *  _name  ;  }  -   (  NSString   *  )  имя  ;  -   (  void  )  setName:  (  NSString   *  )  name  ;  @end  @implementation   Student  -   (  NSString   *  )  name  {      return   _name  ;  }  -   (  void  )  setName:  (  NSString   *  )  name  {      [  _name   Release  ];      _name   =   [  имя   сохраняется  ];  }  @конец 

Используя новый синтаксис Objective-C 2.0, используемый в Mac OS X 10.6 , iOS 4 и Xcode 3.2, генерируем тот же код, что описано выше:

@interface   Student  :  NSObject  @property   (  неатомарный  ,   сохранить  )   NSString   *  name  ;  @end  @implementation   Студент  @synthesize   name   =   _name  ;  @конец 

А начиная с OS X 10.8 и iOS 6 , при использовании Xcode 4.4 и выше синтаксис можно даже упростить:

@interface   Student  :  NSObject  @property   (  неатомарный  ,   сильный  )   NSString   *  name  ;  @end  @implementation   Студент  //Здесь ничего не происходит, и все в порядке.  @конец 
пакет   «Студент»  ;  суб   новый   {      благослови   {},   сдвиг  ;  }  Sub   set_name   {      мой   $self   =   сдвиг  ;      $self  ->  {  имя  }   =   $_  [  0  ];  }  Sub   get_name   {      my   $self   =   сдвиг  ;      вернуть   $self  ->  {  имя  };  }  1  ; 

Или, используя Class::Accessor

пакет   «Студент»  ;  используйте   базу   qw(Class::Accessor)  ;  __PACKAGE__  ->  Follow_best_practice  ;  Студент  ->  mk_accessors  (  qw(имя)  );  1  ; 

Или, используя объектную систему Moose :

пакет   «Студент»  ;  используйте   Муса  ;  # Moose использует имя атрибута в качестве установщика и получателя, свойства чтения и записи  # позволяют нам переопределить это и предоставить наши собственные имена, в этом случае get_name и set_name  имеют   'name'   =>   (  is   =>   'rw'  ,   isa   =>   'Str'  ,   читатель   =>   'get_name'  ,   писатель   =>   'set_name'  );  1  ; 

PHP определяет «волшебные методы» __getи __set для свойств объектов. [9]

В этом примере простого класса, представляющего студента, в котором сохранено только имя, можно видеть, что переменной имя является частным, то есть видимым только из класса Student, а «установщик» и «получатель» являются общедоступными, а именно getName() и setName('name') методы.

класс   Student  {      частная   строка   $name  ;      /**  * @return string Имя.  */      public   function   getName  ()  :   string      {          return   $this  ->  name  ;      }      /**  * @param string $newName Имя, которое нужно установить.  */      публичная   функция   setName  (  строка   $newName  )  :   void      {          $this  ->  name   =   $newName  ;      }  } 

В этом примере используется класс Python с одной переменной, геттером и сеттером.

class   Student  :      # Инициализатор      def   __init__  (  self  ,   name  :   str  )   ->   None  :          # Переменная экземпляра для хранения имени ученика          self  .  _name   =   name      # Метод получения      @property      def   name  (  self  ):          return   self  .  _name      # Метод установки      @name  .  сеттера      определения   имя  (  self  ,   new_name  ):          self  .  _имя   =   новое_имя 
>>>  боб   =   Студент  (  «Боб»  )  >>>  боб  .  имя   Боб  >>>  Боб  .  name   =   "Алиса"  >>>  Боб  .  имя   Алиса  >>>  Боб  .  _name   =   "Чарли"   # обойти установщик  >>>  bob  .  _name   # обойти геттер  Чарли 

В Racket объектная система — это способ организации кода, который поставляется в дополнение к модулям и модулям. Как и в остальном языке, объектная система имеет первоклассные значения, а лексическая область видимости используется для управления доступом к объектам и методам.

#lang  Racket  (  define   Student%    (  class   object%      (  init-поля   имя  )      (  define/public   (  get-name  )   name  )      (  define/public   (  set-name!   new-name  )   (  set!   name   new-name  ))      (  супер-новый  )))  (  define   s   (  new   Student%   [  name   "Alice"  ]))  (  send   s   get-name  )                         ; => "Алиса"  (  отправить   set   -name!   "Bob"  )  (  отправить   name   get-  )                         ; => "Боб" 

Определения структур — это альтернативный способ определения новых типов значений, при этом мутаторы присутствуют, когда это явно требуется:

#lang  Racket  (  struct   Student   (  name  )   #:mutable  )  (  define   s   (  студент   "Алиса"  ))  (  set-student-name!   s   "Bob"  )  (  student-name   s  )                          ; => "Боб" 

В Ruby могут быть определены отдельные методы доступа и мутаторы или конструкции метапрограммирования. attr_reader или attr_accessor может использоваться как для объявления частной переменной в классе, так и для предоставления к ней публичного доступа только для чтения или для чтения и записи соответственно.

Определение отдельных методов доступа и мутаторов создает пространство для предварительной обработки или проверки данных.

class   Student    def   name      @name    end    def   name=  (  значение  )      @name  =  value    end  end 

Простой публичный доступ только для чтения к подразумеваемым @name переменная

класс   Student    attr_reader   :  конец имени 

Простой публичный доступ для чтения и записи к подразумеваемым @name переменная

класс   Student    attr_accessor   :  конец имени 

Ржавчина

[ редактировать ]
struct   Student   {      name  :  String  ,  }  impl   Student   {      fn   name  (  &  self  )   ->  &  String   {          &  self  .  name      }      fn   name_mut  (  &  mut   self  )   ->  &  mut   String   {          &  mut   self  .  имя      }  } 
  age:   aNumber       "Установить возраст получателя как aNumber, если он больше 0 и меньше 150 "     (  Число   между:   0   и:   150  )        ifTrue:  [  возраст   :=   число  ] 
class   Student   {      частное   var   _name  :   String   =   ""      var   name  :   String   {          get   {              return   self  .  _name          }          set   {              self  .  _name   =   новоезначение          }      }  } 

Визуальный Бейсик .NET

[ редактировать ]

Этот пример иллюстрирует идею VB.NET о свойствах, которые используются в классах. Как и в C#, здесь явно используется Get и Set методы.

Открытый   класс   Student      Частное   _name   As   String      открытого   свойства   Имя  ()          Get              Return   _name          End   Get          Set  (  ByVal   значение  )              _name   =   значение          End   Set      End   Property  End   Class 

В VB.NET 2010 автоматически реализуемые свойства можно использовать для создания свойства без использования синтаксиса Get и Set. Обратите внимание, что компилятор создает скрытую переменную, называемую _name, чтобы соответствовать собственности name. Использование другой переменной внутри класса с именем _name приведет к ошибке. Привилегированный доступ к базовой переменной доступен изнутри класса.

Публичный   класс   Student      публичного   свойства   Имя   как   строки  конца   класс 

См. также

[ редактировать ]
  1. ^ Стивен Фукуа (2009). «Автоматические свойства в C# 3.0» . Архивировано из оригинала 13 мая 2011 г. Проверено 19 октября 2009 г.
  2. ^ Тим Ли (13 июля 1998 г.). «Эффективность выполнения функций доступа» .
  3. ^ «CLHS: Макрос ДЕФКЛАСС» . Проверено 29 марта 2011 г.
  4. ^ «CLHS: 7.5.2 Доступ к слотам» . Проверено 29 марта 2011 г.
  5. ^ «MOP: Определения слотов» . Проверено 29 марта 2011 г.
  6. ^ «Функции — язык программирования D» . Проверено 13 января 2013 г.
  7. ^ «Стиль Д» . Проверено 1 февраля 2013 г.
  8. ^ «Object.prototype.__defineGetter__() — JavaScript | MDN» . http://developer.mozilla.org . Проверено 6 июля 2021 г.
  9. ^ «PHP: Перегрузка — Руководство» . www.php.net . Проверено 6 июля 2021 г.
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: a0ec2c8abc4e835a102f31c1a408379f__1721473320
URL1:https://arc.ask3.ru/arc/aa/a0/9f/a0ec2c8abc4e835a102f31c1a408379f.html
Заголовок, (Title) документа по адресу, URL1:
Mutator method - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)