Перейти к содержимому

Что такое сеттер в программировании

  • автор:

Сеттер или геттер-ссылка — как сделать правильный выбор?

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

Сделать это можно двумя способами:

  • С помощью сеттера, метода, который принимает новое значение атрибута в качестве аргумента.
  • С помощью геттера-ссылки (reference-getter), метода, который возвращает ссылку на сам атрибут.

Вот небольшой пример, показывающий, как с помощью двух этих методов получить доступ к полю bar .

class Foo < int m_bar; public: //Сеттер void set_bar(int bar) < m_bar = bar; >//Геттер-ссылка int & get_bar() < return m_bar; >>; int main() < Foo foo; //Редактирование через сеттер foo.set_bar(42); //Редактирование с помощью геттер-ссылки foo.get_bar() = 84; return 0; >

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

Сеттер

Сеттер по отношению к классу является интерфейсом только для записи (write-only). Вы указываете значение, и соответственно обновляете класс.

Зачастую он более или менее напрямую обновляет атрибут, копируя/перемещая(move) предоставленные вами данные.

// Самый примитивный сеттер void set_foo(int foo)
// Сеттер, который делает проверку перед присваиванием void set_foo(Foo foo)
// move-сеттер void set_big_foo(BigFoo && big_foo) < m_big_foo = std::forward(big_foo); >
Геттер-ссылка

Геттер-ссылка (reference-getter) представляет собой метод, который возвращает ссылку на атрибут, что дает непосредственный доступ к нему, в том числе предоставляя возможность его редактирования.

Этот метод особенно полезен для атрибутов-объектов для того, чтобы вы могли вызывать неконстантные методы непосредственно на них.

// Here is the implementation of the reference-getter Foo & MyClass::get_foo() < return m_foo; >// . // Used to edit an attribute myClass.getFoo().bar = 42; // Used to call a non-const method myClass.getFoo().udpate();
Какой метод выбрать?

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

Когда вам нужно пересоздать данные и поместить их на место уже существующих, вам пригодится сеттер. Он также подходит для редактирования простых данных (целые числа, значения чисел с плавающей запятой, указатели и т. д.) или если вам нужно подставить полностью новое значение. Еще один вариант использования сеттеров: когда вы намеренно хотите дать пользователю возможность только редактировать данные, но не читать.

Геттер-ссылка вам пригодится для редактирования данных атрибута (а не атрибута целиком). Часто нам необходимо отредактировать только часть атрибута или вызвать для них неконстантный метод.

Другими словами, сеттер заменяет атрибут, а геттер-ссылка редактирует атрибут.

Пример

Рассмотрим следующий код:

#include using namespace std; struct Item < bool validity; int value; >; class Foo < public: Foo(size_t size) : m_max_size(size), m_data(size, ) <> void set_max_size(size_t max_size) < m_max_size = max_size; >Item & get_item(size_t index) < return m_data.at(index); >size_t get_data_size() const < return m_data.size(); >private: bool m_max_size; std::vector m_data; >; static void set_foo_size(Foo & foo, size_t new_size)

В коде представлен простой класс, который содержит набор данных (Item’ы). Эти данные могут быть валидными или невалидными ( true — валидные, false — невалидные).

Затем мы реализуем небольшую функцию, которая изменяет размер коллекции, не удаляя никаких элементов. Элементы, выходящие за заданный размер, становятся невалидными.

Мы задаем значение m_max_size с помощью сеттера, так как это обычное целое число, значение которого меняется при изменении размера коллекции.

С помощью геттер-ссылки мы можем получить доступ к каждому Item ‘у из m_data , так как нам не всегда требуется полностью удалять item , иногда нам необходимо просто отредактировать его часть.

Мы могли бы редактировать валидность, используя более специфичный сеттер, например:

class Foo < // . void set_item_validity(size_t index, bool validity) < m_data.at(index).validity = validity; >// . >;

Сделав так, мы бы потеряли возможность редактировать value Item ,поэтому это решение полностью зависит от деталей вашей реализации.

Однако, пожалуйста, помните, что писать сеттеры и для value и для validity является плохой практикой. Делать это в корзине данных с двумя атрибутами вряд ли будет правильным решением, потому что как только ваша реализация начнет расти, ваша кодовая база будет переполнена бесполезными аксессорами. Вам нужен полный доступ? Так и реализуйте полный доступ.

Заключение

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

Материал подготовлен в рамках специализации «C++ Developer».

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

  • Блог компании OTUS
  • Программирование
  • C++

Сеттер программирование У этого термина существуют и другие значения см Сеттер значения Сеттер англ setter также устанав

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

Примеры Править

public class ScheduleTask  private int hours; public void setHours(int hours)  if ((hours >= 0) && (hours  24)) this.hours = hours; > > 

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

В C# благодаря синтаксическим возможностям (контекстные ключевые слова set и value — использующееся только в сеттере) чаще применяется другая методика:

public class ScheduleTask  private int hours; public int Hours  set  if ( (value >= 0) && (value  24) )  hours = value; > > > > 

При этом возможно использование и через публичный метод, так как фактически конструкцию set < . >компилятор C# преобразует в метод класса.

Сеттер в VB.NET обязан иметь модификатор WriteOnly, если не будет реализован геттер:

Public Class Foo Private m_Data As Integer 'Закрытое поле с данными Public Property Message As Integer 'Автореализуемое свойство, начиная с VB 10.0 Public WriteOnly Property Data As Integer 'Открытое свойство только для записи Set(Value As Integer) m_Data = Value End Set End Property End Class 

В статье не хватает ссылок на источники (см. рекомендации по поиску).

Информация должна быть проверяема, иначе она может быть удалена. Вы можете отредактировать статью, добавив ссылки на авторитетные источники в виде сносок. ( 28 сентября 2014 )

Википедия, чтение, книга, библиотека, поиск, нажмите, истории, книги, статьи, wikipedia, учить, информация, история, скачать, скачать бесплатно, mp3, видео, mp4, 3gp, jpg, jpeg, gif, png, картинка, музыка, песня, фильм, игра, игры

Дата публикации: Октябрь 05, 2023, 20:28 pm
Самые читаемые

Пивоваров, Олег (Герой Российской Федерации)

Пибор Пост

Пинг (река)

Пино, Франсуа

Пикколо

Пикатрикс

Пикар, Мари-Жорж

Пионерская улица (Казань, Бауманский район)

Плуизи

Плаха (роман)

© Copyright 2021, Все права защищены.

U etogo termina sushestvuyut i drugie znacheniya sm Setter znacheniya Setter angl setter takzhe ustanavlivayushij metod modificiruyushij metod mutator metod ispolzuemyj v obektno orientirovannom programmirovanii dlya prisvoeniya kakogo libo znacheniya inkapsulirovannomu polyu naprimer obrabotav pri etom nedopustimye prisvaivaniya Chasto realizuetsya v pare s metodom getterom pozvolyayushim poluchat znachenie polya klassa Primery PravitPrimer na Java public class ScheduleTask private int hours public void setHours int hours if hours gt 0 amp amp hours lt 24 this hours hours Zdes dlya izmeneniya skrytogo polya hours nuzhno ispolzovat setter setHours kotoryj budet sledit za tem chtoby ono prinimalo tolko dopustimye znacheniya V C blagodarya sintaksicheskim vozmozhnostyam kontekstnye klyuchevye slova set i value ispolzuyusheesya tolko v settere chashe primenyaetsya drugaya metodika public class ScheduleTask private int hours public int Hours set if value gt 0 amp amp value lt 24 hours value Pri etom vozmozhno ispolzovanie i cherez publichnyj metod tak kak fakticheski konstrukciyu set kompilyator C preobrazuet v metod klassa Setter v VB NET obyazan imet modifikator WriteOnly esli ne budet realizovan getter Public Class Foo Private m Data As Integer Zakrytoe pole s dannymi Public Property Message As Integer Avtorealizuemoe svojstvo nachinaya s VB 10 0 Public WriteOnly Property Data As Integer Otkrytoe svojstvo tolko dlya zapisi Set Value As Integer m Data Value End Set End Property End Class V state ne hvataet ssylok na istochniki sm rekomendacii po poisku Informaciya dolzhna byt proveryaema inache ona mozhet byt udalena Vy mozhete otredaktirovat statyu dobaviv ssylki na avtoritetnye istochniki v vide snosok 28 sentyabrya 2014 Istochnik https ru wikipedia org w index php title Setter programmirovanie amp oldid 114775007

Что такое геттеры и сеттеры в программировании

Это будет текст об архитектуре объектно-ориентированных программ. Это для тех, кто планирует серьёзно заниматься разработкой.

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

Например, можно представить, что автомобиль — это объект: у него внутри много сложных деталей и связей между ними. Но снаружи всё относительно просто: руль, педали, переключатели, фары, спидометр, тахометр, индикатор температуры, уровня топлива и т. д. Чтобы этим управлять, нам не нужно знать внутреннее устройство машины, а достаточно изучить основные внешние функции.

Что такое геттеры и сеттеры в программировании

Одно из понятий ООП — инкапсуляция, и в нём часто применяется такая идея:

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

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

Такие механизмы доступа к данным через посредника называются геттеры и сеттеры.

Что такое геттер и сеттер

Эти слова пришли из английского от слов get (получать) и set (устанавливать).

Задача геттера — получить данные о чём-то внутри объекта и передать их наружу. Например, водитель не может постоянно заглядывать в бензобак и смотреть, сколько бензина. Вместо этого водитель смотрит на индикатор топлива — тот показывает, сколько бензина осталось в баке. Индикатор топлива — это геттер: он берёт данные из объекта (автомобиль) и отдаёт их тому, кто их попросил (водитель).

Сеттер работает иначе: он меняет значения внутри объекта. В примере с автомобилем педаль газа — это сеттер: в зависимости от силы нажатия она изменяет объём впрыска топлива в двигатель. Так производители защищают двигатель от нештатных ситуаций: даже при нажатии педали газа в пол в двигатель попадёт безопасное количество топлива.

Геттеры и сеттеры в программировании

Чаще всего в программировании эти инструменты используются как метод или интерфейс объекта: вы создаёте объект и указываете, что с ним можно делать. Поясним на примере.

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

// Объявляем новый объект-константу с помощью стрелочной функции const createCounter = () => < // Доступ к этой переменной возможен только внутри этой функции, снаружи поменять её не получится let count = 0; // Что возвращает функция return (< // Если вызван метод upvote(), увеличиваем переменную счётчика на 1 upvote: () =>count += 1, // Если вызван метод getVoteCount, возвращаем значение счётчика getVoteCount: () => count.toLocaleString() >); >; // Создаём новый объект на основе своего const counter = createCounter(); // Кликаем пару раз, увеличивая счётчик на единицу // Другим способом мы не сможем его изменить counter.upvote(); counter.upvote(); // Смотрим, что получилось в итоге (2) console.log(counter.getVoteCount());

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

// ❌ Кажется, что это тоже сработает, но на самом деле значение счётчика не изменится
counter.count = 100

// На выходе всё так же будет число 2
console.log(counter.getCount());

Что такое геттеры и сеттеры в программировании

Зачем они нужны

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

Получите ИТ-профессию

В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.

Свойства — геттеры и сеттеры

Первый тип это свойства-данные (data properties). Мы уже знаем, как работать с ними. Все свойства, которые мы использовали до текущего момента, были свойствами-данными.

Второй тип свойств мы ещё не рассматривали. Это свойства-аксессоры (accessor properties). По своей сути это функции, которые используются для присвоения и получения значения, но во внешнем коде они выглядят как обычные свойства объекта.

Геттеры и сеттеры

Свойства-аксессоры представлены методами: «геттер» – для чтения и «сеттер» – для записи. При литеральном объявлении объекта они обозначаются get и set :

let obj = < get propName() < // геттер, срабатывает при чтении obj.propName >, set propName(value) < // сеттер, срабатывает при записи obj.propName = value >>;

Геттер срабатывает, когда obj.propName читается, сеттер – когда значение присваивается.

Например, у нас есть объект user со свойствами name и surname :

let user = < name: "John", surname: "Smith" >;

А теперь добавим свойство объекта fullName для полного имени, которое в нашем случае «John Smith» . Само собой, мы не хотим дублировать уже имеющуюся информацию, так что реализуем его при помощи аксессора:

let user = < name: "John", surname: "Smith", get fullName() < return `$$`; > >; alert(user.fullName); // John Smith

Снаружи свойство-аксессор выглядит как обычное свойство. В этом и заключается смысл свойств-аксессоров. Мы не вызываем user.fullName как функцию, а читаем как обычное свойство: геттер выполнит всю работу за кулисами.

На данный момент у fullName есть только геттер. Если мы попытаемся назначить user.fullName= , произойдёт ошибка:

let user = < get fullName() < return `. `; >>; user.fullName = "Тест"; // Ошибка (у свойства есть только геттер)

Давайте исправим это, добавив сеттер для user.fullName :

let user = < name: "John", surname: "Smith", get fullName() < return `$$`; >, set fullName(value) < [this.name, this.surname] = value.split(" "); >>; // set fullName запустится с данным значением user.fullName = "Alice Cooper"; alert(user.name); // Alice alert(user.surname); // Cooper

В итоге мы получили «виртуальное» свойство fullName . Его можно прочитать и изменить.

Дескрипторы свойств доступа

Дескрипторы свойств-аксессоров отличаются от «обычных» свойств-данных.

Свойства-аксессоры не имеют value и writable , но взамен предлагают функции get и set .

То есть, дескриптор аксессора может иметь:

  • get – функция без аргументов, которая сработает при чтении свойства,
  • set – функция, принимающая один аргумент, вызываемая при присвоении свойства,
  • enumerable – то же самое, что и для свойств-данных,
  • configurable – то же самое, что и для свойств-данных.

Например, для создания аксессора fullName при помощи defineProperty мы можем передать дескриптор с использованием get и set :

let user = < name: "John", surname: "Smith" >; Object.defineProperty(user, 'fullName', < get() < return `$$`; >, set(value) < [this.name, this.surname] = value.split(" "); >>); alert(user.fullName); // John Smith for(let key in user) alert(key); // name, surname

Ещё раз заметим, что свойство объекта может быть либо свойством-аксессором (с методами get/set ), либо свойством-данным (со значением value ).

При попытке указать и get , и value в одном дескрипторе будет ошибка:

// Error: Invalid property descriptor. Object.defineProperty(<>, 'prop', < get() < return 1 >, value: 2 >);

Умные геттеры/сеттеры

Геттеры/сеттеры можно использовать как обёртки над «реальными» значениями свойств, чтобы получить больше контроля над операциями с ними.

Например, если мы хотим запретить устанавливать короткое имя для user , мы можем использовать сеттер name для проверки, а само значение хранить в отдельном свойстве _name :

let user = < get name() < return this._name; >, set name(value) < if (value.length < 4) < alert("Имя слишком короткое, должно быть более 4 символов"); return; >this._name = value; > >; user.name = "Pete"; alert(user.name); // Pete user.name = ""; // Имя слишком короткое. 

Таким образом, само имя хранится в _name , доступ к которому производится через геттер и сеттер.

Технически, внешний код всё ещё может получить доступ к имени напрямую с помощью user._name , но существует широко известное соглашение о том, что свойства, которые начинаются с символа «_» , являются внутренними, и к ним не следует обращаться из-за пределов объекта.

Использование для совместимости

У аксессоров есть интересная область применения – они позволяют в любой момент взять «обычное» свойство и изменить его поведение, поменяв на геттер и сеттер.

Например, представим, что мы начали реализовывать объект user , используя свойства-данные имя name и возраст age :

function User(name, age) < this.name = name; this.age = age; >let john = new User("John", 25); alert( john.age ); // 25

…Но рано или поздно всё может измениться. Взамен возраста age мы можем решить хранить дату рождения birthday , потому что так более точно и удобно:

function User(name, birthday) < this.name = name; this.birthday = birthday; >let john = new User("John", new Date(1992, 6, 1));

Что нам делать со старым кодом, который использует свойство age ?

Мы можем попытаться найти все такие места и изменить их, но это отнимает время и может быть невыполнимо, если код используется другими людьми. И кроме того, age – это отличное свойство для user , верно?

Давайте его сохраним.

Добавление геттера для age решит проблему:

function User(name, birthday) < this.name = name; this.birthday = birthday; // возраст рассчитывается из текущей даты и дня рождения Object.defineProperty(this, "age", < get() < let todayYear = new Date().getFullYear(); return todayYear - this.birthday.getFullYear(); >>); > let john = new User("John", new Date(1992, 6, 1)); alert( john.birthday ); // доступен как день рождения alert( john.age ); // . так и возраст

Теперь старый код тоже работает, и у нас есть отличное дополнительное свойство!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *