Объекты
Как мы знаем из главы Типы данных, в JavaScript существует 8 типов данных. Семь из них называются «примитивными», так как содержат только одно значение (будь то строка, число или что-то другое).
Объекты же используются для хранения коллекций различных значений и более сложных сущностей. В JavaScript объекты используются очень часто, это одна из основ языка. Поэтому мы должны понять их, прежде чем углубляться куда-либо ещё.
Объект может быть создан с помощью фигурных скобок <…>с необязательным списком свойств. Свойство – это пара «ключ: значение», где ключ – это строка (также называемая «именем свойства»), а значение может быть чем угодно.
Мы можем представить объект в виде ящика с подписанными папками. Каждый элемент данных хранится в своей папке, на которой написан ключ. По ключу папку легко найти, удалить или добавить в неё что-либо.
Пустой объект («пустой ящик») можно создать, используя один из двух вариантов синтаксиса:
Обычно используют вариант с фигурными скобками <. >. Такое объявление называют литералом объекта или литеральной нотацией.
Литералы и свойства
При использовании литерального синтаксиса <. >мы сразу можем поместить в объект несколько свойств в виде пар «ключ: значение»:
У каждого свойства есть ключ (также называемый «имя» или «идентификатор»). После имени свойства следует двоеточие ":" , и затем указывается значение свойства. Если в объекте несколько свойств, то они перечисляются через запятую.
В объекте user сейчас находятся два свойства:
- Первое свойство с именем "name" и значением "John" .
- Второе свойство с именем "age" и значением 30 .
Можно сказать, что наш объект user – это ящик с двумя папками, подписанными «name» и «age».
Мы можем в любой момент добавить в него новые папки, удалить папки или прочитать содержимое любой папки.
Для обращения к свойствам используется запись «через точку»:
Значение может быть любого типа. Давайте добавим свойство с логическим значением:
Для удаления свойства мы можем использовать оператор delete :
Имя свойства может состоять из нескольких слов, но тогда оно должно быть заключено в кавычки:
Последнее свойство объекта может заканчиваться запятой:
Это называется «висячая запятая». Такой подход упрощает добавление, удаление и перемещение свойств, так как все строки объекта становятся одинаковыми.
Объект, объявленный через const , может быть изменён.
Может показаться, что строка (*) должна вызвать ошибку, но нет, здесь всё в порядке. Дело в том, что объявление const защищает от изменений только саму переменную user , а не её содержимое.
Определение const выдаст ошибку только если мы присвоим переменной другое значение: user=. .
Есть ещё один способ сделать константами свойства объекта, который мы рассмотрим в главе Флаги и дескрипторы свойств.
Квадратные скобки
Для свойств, имена которых состоят из нескольких слов, доступ к значению «через точку» не работает:
JavaScript видит, что мы обращаемся к свойству user.likes , а затем идёт непонятное слово birds . В итоге синтаксическая ошибка.
Точка требует, чтобы ключ был именован по правилам именования переменных. То есть не имел пробелов, не начинался с цифры и не содержал специальные символы, кроме $ и _ .
Для таких случаев существует альтернативный способ доступа к свойствам через квадратные скобки. Такой способ сработает с любым именем свойства:
Сейчас всё в порядке. Обратите внимание, что строка в квадратных скобках заключена в кавычки (подойдёт любой тип кавычек).
Квадратные скобки также позволяют обратиться к свойству, имя которого может быть результатом выражения. Например, имя свойства может храниться в переменной:
Здесь переменная key может быть вычислена во время выполнения кода или зависеть от пользовательского ввода. После этого мы используем её для доступа к свойству. Это даёт нам большую гибкость.
Работа с объектами
JavaScript спроектирован на основе простой парадигмы. В основе концепции лежат простые объекты. Объект — это набор свойств, и каждое свойство состоит из имени и значения, ассоциированного с этим именем. Значением свойства может быть функция, которую можно назвать методом объекта. В дополнение к встроенным в браузер объектам, вы можете определить свои собственные объекты. Эта глава описывает как пользоваться объектами, свойствами, функциями и методами, а также как создавать свои собственные объекты.
Обзор объектов
Объекты в JavaScript, как и во многих других языках программирования, похожи на объекты реальной жизни. Концепцию объектов JavaScript легче понять, проводя параллели с реально существующими в жизни объектами.
В JavaScript объект — это самостоятельная единица, имеющая свойства и определённый тип. Сравним, например, с чашкой. У чашки есть цвет, форма, вес, материал, из которого она сделана, и т.д. Точно так же, объекты JavaScript имеют свойства, которые определяют их характеристики.
Объекты и свойства
В JavaScript объект имеет свойства, ассоциированные с ним. Свойство объекта можно понимать как переменную, закреплённую за объектом. Свойства объекта в сущности являются теми же самыми переменными JavaScript, за тем исключением, что они закреплены за объектом. Свойства объекта определяют его характеристики. Получить доступ к свойству объекта можно с помощью точечной записи:
Как и все переменные JavaScript, имя объекта (которое тоже может быть переменной) и имя свойства являются чувствительными к регистру. Вы можете определить свойство указав его значение. Например, давайте создадим объект myCar и определим его свойства make , model , и year следующим образом:
Неопределённые свойства объекта являются undefined (а не null ).
Свойства объектов JavaScript также могут быть доступны или заданы с использованием скобочной записи (более подробно см. property accessors). Объекты иногда называются ассоциативными массивами, поскольку каждое свойство связано со строковым значением, которое можно использовать для доступа к нему. Так, например, вы можете получить доступ к свойствам объекта myCar следующим образом:
Имена свойств объекта могут быть строками JavaScript, или тем, что может быть сконвертировано в строку, включая пустую строку. Как бы то ни было, доступ к любому имени свойства, которое содержит невалидный JavaScript идентификатор (например, имя свойства содержит в себе пробел и тире или начинается с цифры), может быть получен с использованием квадратных скобок. Этот способ записи также полезен, когда имена свойств должны быть динамически определены (когда имя свойства не определено до момента исполнения). Примеры далее:
Обратите внимание, что все ключи с квадратными скобками преобразуются в тип String, поскольку объекты в JavaScript могут иметь в качестве ключа только тип String. Например, в приведённом выше коде, когда ключ obj добавляется в myObj , JavaScript вызывает метод obj.toString () и использует эту результирующую строку в качестве нового ключа.
Вы также можете получить доступ к свойствам, используя значение строки, которое хранится в переменной:
Вы можете пользоваться квадратными скобками в конструкции for. in чтобы выполнить итерацию всех свойств объекта, для которых она разрешена. Чтобы показать как это работает, следующая функция показывает все свойства объекта, когда вы передаёте в неё сам объект и его имя как аргументы функции:
Так что если вызвать эту функцию вот так showProps(myCar, «myCar»), то получим результат:
Перечисление всех свойств объекта
Начиная с ECMAScript 5, есть три способа перечислить все свойства объекта (получить их список):
- циклы for. in (en-US) Этот метод перебирает все перечисляемые свойства объекта и его цепочку прототипов
- Object.keys(o) (en-US) Этот метод возвращает массив со всеми собственными (те, что в цепочке прототипов, не войдут в массив) именами перечисляемых свойств объекта o .
- Object.getOwnPropertyNames(o) (en-US) Этот метод возвращает массив содержащий все имена своих свойств (перечисляемых и неперечисляемых) объекта o .
До ECMAScript 5 не было встроенного способа перечислить все свойства объекта. Однако это можно сделать с помощью следующей функции:
Это может быть полезно для обнаружения скрытых (hidden) свойств (свойства в цепочке прототипа, которые недоступны через объект, в случае, если другое свойство имеет такое же имя в предыдущем звене из цепочки прототипа). Перечислить доступные свойства можно, если удалить дубликаты из массива.
Создание новых объектов
JavaScript содержит набор встроенных объектов. Также вы можете создавать свои объекты. Начиная с JavaScript 1.2, вы можете создавать объект с помощью инициализатора объекта. Другой способ — создать функцию-конструктор и сделать экземпляр объекта с помощью этой функции и оператора new .
Использование инициализаторов объекта
Помимо создания объектов с помощью функции-конструктора вы можете создавать объекты и другим, особым способом. Фактически, вы можете записать объект синтаксически, и он будет создан интерпретатором автоматически во время выполнения. Эта синтаксическая схема приведена ниже:
здесь obj — это имя нового объекта, каждое property_i — это идентификатор (имя, число или строковый литерал), и каждый value_i — это значения, назначенные property_i . Имя obj и ссылка объекта на него необязательна; если далее вам не надо будет ссылаться на данный объект, то вам не обязательно назначать объект переменной. (Обратите внимание, что вам потребуется обернуть литерал объекта в скобки, если объект находится в месте, где ожидается инструкция, чтобы интерпретатор не перепутал его с блоком.)
Если объект создан при помощи инициализатора объектов на высшем уровне скрипта, то JavaScript интерпретирует объект каждый раз, когда анализирует выражение, содержащее объект, записанный как литерал. Плюс, если пользоваться функцией инициализатором, то он будет создаваться каждый раз, когда функция вызывается.
Следующая инструкция создаёт объект и назначает его переменной x , когда выражение cond истинно.
Следующий пример создаёт объект myHonda с тремя свойствами. Заметьте, что свойство engine — это также объект со своими собственными свойствами.
Вы также можете использовать инициализатор объекта для создания массивов. Смотрите array literals.
До JavaScript 1.1 не было возможности пользоваться инициализаторами объекта. Единственный способ создавать объекты — это пользоваться функциями-конструкторами или функциями других объектов, предназначенных для этой цели. Смотрите Using a constructor function.
Использование функции конструктора
Другой способ создать объект в два шага описан ниже:
- Определите тип объекта, написав функцию-конструктор. Название такой функции, как правило, начинается с заглавной буквы.
- Создайте экземпляр объекта с помощью ключевого слова new .
Чтобы определить тип объекта создайте функцию, которая определяет тип объекта, его имя, свойства и методы. Например предположим, что вы хотите создать тип объекта для описания машин. Вы хотите, чтобы объект этого типа назывался car , и вы хотите, чтобы у него были свойства make, model, и year. Чтобы сделать это, напишите следующую функцию:
Заметьте, что используется this чтобы присвоить значения (переданные как аргументы функции) свойствам объекта.
Теперь вы можете создать объект, называемый mycar , следующим образом:
Эта инструкция создаёт объект типа Car со ссылкой mycar и присваивает определённые значения его свойствам. Значением mycar.make станет строка «Eagle», mycar.year — это целое число 1993, и так далее.
Вы можете создать столько объектов car, сколько нужно, просто вызывая new . Например:
Объект может иметь свойство, которое будет другим объектом. Например, далее определяется объект типа Person следующим образом:
и затем создать два новых экземпляра объектов Person как показано далее:
Затем, вы можете переписать определение car и включить в него свойство owner , которому назначить объект person следующим образом:
Затем, чтобы создать экземпляры новых объектов, выполните следующие инструкции:
Заметьте, что вместо того, чтобы передавать строку, литерал или целое число при создании новых объектов, в выражениях выше передаются объекты rand и ken как аргумент функции. Теперь, если вам нужно узнать имя владельца car2, это можно сделать следующим образом:
Заметьте, что в любое время вы можете добавить новое свойство ранее созданному объекту. Например, выражение
добавляет свойство color к car1, и устанавливает его значение равным «black.» Как бы там ни было, это не влияет на любые другие объекты. Чтобы добавить новое свойство всем объектам одного типа, вы должны добавить свойство в определение типа объекта car .
Использование метода Object.create
Объекты также можно создавать с помощью метода Object.create . Этот метод очень удобен, так как позволяет вам указывать объект прототип для нового вашего объекта без определения функции конструктора.
Наследование
Все объекты в JavaScript наследуются как минимум от другого объекта. Объект, от которого произошло наследование называется прототипом, и унаследованные свойства могут быть найдены в объекте prototype конструктора.
Индексы свойств объекта
В JavaScript 1.0 вы можете сослаться на свойства объекта либо по его имени, либо по его порядковому индексу. В JavaScript 1.1 и позже, если вы изначально определили свойство по имени, вы всегда должны ссылаться на него по его имени, и если вы изначально определили свойство по индексу, то должны ссылаться на него по его индексу.
Это ограничение налагается когда вы создаёте объект и его свойства с помощью функции конструктора (как мы это делали ранее с типом Car ) и когда вы определяете индивидуальные свойства явно (например, myCar.color = «red» ). Если вы изначально определили свойство объекта через индекс, например myCar[5] = «25 mpg» , то впоследствии сослаться на это свойство можно только так myCar[5] .
Исключение из правил — объекты, отображаемые из HTML, например массив forms . Вы всегда можете сослаться на объекты в этих массивах или используя их индекс (который основывается на порядке появления в HTML документе), или по их именам (если таковые были определены). Например, если второй html-тег <FORM> в документе имеет значение атрибута NAME равное «myForm», вы можете сослаться на эту форму вот так: document.forms[1] или document.forms[«myForm»] или document.myForm .
Определение свойств для типа объекта
Вы можете добавить свойство к ранее определённому типу объекта воспользовавшись специальным свойством prototype . Через prototype создаётся свойство, единое для всех объектов данного типа, а не одного экземпляра этого типа объекта. Следующий код демонстрирует это, добавляя свойство color ко всем объектам типа car , а затем присваивая значение свойству color объекта car1 .
Определение методов
Метод — это функция, ассоциированная с объектом или, проще говоря, метод — это свойство объекта, являющееся функцией. Методы определяются так же, как и обычные функции, за тем исключением, что они присваиваются свойству объекта. Например вот так:
где objectName — это существующий объект, methodname — это имя, которое вы присваиваете методу, и function_name — это имя самой функции.
Затем вы можете вызвать метод в контексте объекта следующим образом:
Вы можете определять методы для типа объекта, включая определение метода в функцию конструктора объекта. Например, вы можете определить функцию, которая форматирует и отображает свойства до этого определённых объектов car . Например,
где pretty_print — это функция отображения горизонтальной линии и строки. Заметьте, что использование this позволяет ссылаться на объект, которому принадлежит метод.
Вы можете сделать эту функцию методом car, добавив инструкцию
к определению объекта. Таким образом, полное определение car примет следующий вид:
Теперь вы можете вызвать метод displayCar для каждого из объектов как показано ниже:
Использование this для ссылки на объект
В JavaScript есть специальное ключевое слово this, которое вы можете использовать внутри метода, чтобы ссылаться на текущий объект. Предположим, у вас есть функция validate, которая сверяет свойство value, переданного ей объекта с некоторыми верхним и нижним значениями:
Вы можете вызвать эту функцию validate в каждом элементе формы, в обработчике события onchange . Используйте this для доступа к этому элементу, как это сделано ниже:
В общем случае, this ссылается на объект, вызвавший метод.
Через this можно обратиться и к родительской форме элемента, воспользовавшись свойством form . В следующем примере форма myForm содержит элемент ввода Text и кнопку button1 . Когда пользователь нажимает кнопку, значению объекта Text назначается имя формы. Обработчик событий кнопки onclick пользуется this.form чтобы сослаться на текущую форму, myForm .
Определение геттеров и сеттеров
Геттер(от англ. get — получить) — это метод, который получает значение определённого свойства. _Сеттер (от англ. set* — *присвоить) — это метод, который присваивает значение определённому свойству объекта. Вы можете определить геттеры и сеттеры для любых из встроенных или определённых вами объектов, которые поддерживают добавление новых свойств. Синтаксис определения геттеров и сеттеров использует литеральный синтаксис объектов.
Ниже проиллюстрировано, как могут работать геттеры и сеттеры в объекте определённом пользователем:
Объект o получит следующие свойства:
- o.a — число
- o.b — геттер, который возвращает o.a плюс 1
- o.c — сеттер, который присваивает значение o.a половине значения которое передано в o.c
Следует особо отметить, что имена функций, указанные в литеральной форме «[gs]et propertyName() < >» не будут в действительности являться именами геттера и сеттера. Чтобы задать в качестве геттера и сеттера функции с явно определёнными именами, используйте метод Object.defineProperty (или его устаревший аналог Object.prototype.__defineGetter__ ).
В коде ниже показано, как с помощью геттера и сеттера можно расширить прототип объекта Date и добавить ему свойство year, которое будет работать у всех экземпляров класса Date . Этот код использует существующие методы класса Date — getFullYear и setFullYear для работы геттера и сеттера.
Определение геттера и сеттера для свойства year :
Использование свойства year заданного геттером и сеттером:
В принципе, геттеры и сеттеры могут быть либо:
- определены при использовании Инициализаторов объекта, или
- добавлены существующему объекту в любой момент, при использовании методов добавления геттеров и сеттеров.
Когда определение геттера и сеттера использует инициализаторы объекта, всё что вам нужно, это дополнить геттер префиксом get а сеттер префиксом set . При этом, метод геттера не должен ожидать каких либо параметров, в то время как метод сеттера принимает один единственный параметр (новое значение для присвоения свойству). Например:
Геттеры и сеттеры, могут быть добавлены существующему объекту в любой момент, при помощи метода Object.defineProperties . Первый параметр этого метода — объект, которому вы хотите присвоить геттер и сеттер. Второй параметр — это объект, имена свойств которого будут соответствовать именам создаваемых свойств, а значения — объекты определяющие геттер и сеттер создаваемых свойств. В следующем примере создаются в точности такие же геттер и сеттер, как и в примере выше:
То, какую из двух форм использовать для определения свойств, зависит от вашего стиля программирования и стоящей перед вами задачи. Если вы уже используете инициализатор объекта для определения прототипа, то, скорее всего, в большинстве случаев, вы воспользуетесь первой формой. Она более компактна и естественна. Однако, не редко, вторая форма является единственно возможной, в случаях, когда вы работаете с существующим объектом без доступа к его определению. Вторая форма наилучшим образом отражает динамическую природу JavaScript — но может сделать код сложным для чтения и понимания.
Удаление свойств
Вы можете удалить свойство используя оператор delete . Следующий код показывает как удалить свойство.
Вы также можете воспользоваться delete чтобы удалить глобальную переменную, если ключевое слово var не было использовано при её объявлении:
Смотри [delete](Expressions_and_operators#delete) чтобы получить дополнительную информацию.
Сравнение объектов
В JavaScript объекты имеют ссылочный тип. Два отдельных объекта никогда не будут равными, даже если они имеют равный набор свойств. Только сравнение двух ссылок на один и тот же объект вернёт true.
Свойства объекта
Свойство — интерфейс доступа программиста к соответствующей переменной объекта. Свойство может быть просто другим именем переменной (поля) объекта, тогда компилятор подставляет на место свойства переменную. Если это не так — то при обращении программиста к свойству вызывается определённый метод, который выполняет определённые операции с объектом. В некоторых языках при обращении к свойству всегда вызывается метод, который, в простейшем случае, просто выполняет запись или чтение определённой переменной объекта.
Свойства повышают гибкость и безопасность программирования и являются важным инструментом, применяемым при разработке ПО.
Содержание
Методы свойств
Во многих языках программирования свойства реализуются в виде пары методов: метод, получающий текущее значение свойства, называется акцессор (accessor); метод, задающий новое значение свойства — мутатор (mutator). В языках программирования, не поддерживающих свойства, например C++ и
Принято называть методы свойств именем свойства с приставками get и set: например, для свойства Xyzzy — get_Xyzzy и set_Xyzzy (традиционный стиль Си) либо GetXyzzy и SetXyzzy (стиль getter и setter.
Свойства в C#
Свойства в C# — поля с логическим блоком, в котором есть ключевые слова get и set .
Пример класса со свойством:
Свойства в Delphi
Для описания свойства в property .
Пример класса со свойством:
Свойства в ActionScript
Свойства в Ruby
Описания свойства в
Однако простое обращение к внутренней переменной объекта может быть заменено на вызов метода attr_accessor :duration
Более интересным будет пример создания свойства duration_in_minutes, которое будет возвращать или устанавливать время длительности в минутах:
При этом изменение свойства duration_in_minutes повлияет на свойство duration. Например
Wikimedia Foundation . 2010 .
Полезное
Смотреть что такое «Свойства объекта» в других словарях:
Свойства — Свойство (в философии, математике и логике) атрибут предмета (объекта). Например, о красном предмете говорится, что он обладает свойством красноты. Свойство можно рассматривать как форму предмета самого по себе, притом, что он может обладать и… … Википедия
Свойства алгоритма — Свойства алгоритмов К алгоритму предъявляется ряд требований: Определенность, т.е. он должен быть точен, общепонятен, исключать возможность произвольного толкования. Массовость, т.е. чтобы его можно было применить к однотипным задачам.… … Википедия
свойства — Атрибуты объекта, которые однозначно определяют его и позволяют отличить от аналогичных объектов по ряду признаков, таких как позиция, форма сигнала, адрес и т.п. [Л.М. Невдяев. Телекоммуникационные технологии. Англо русский толковый словарь… … Справочник технического переводчика
ГОСТ Р 52361-2005: Контроль объекта аналитический. Термины и определения — Терминология ГОСТ Р 52361 2005: Контроль объекта аналитический. Термины и определения оригинал документа: 49 аккредитованная аналитическая лаборатория: Аналитическая лаборатория, получившая в результате ее проверки органом по аккредитации… … Словарь-справочник терминов нормативно-технической документации
погрешность отбора пробы вещества [материала] (объекта аналитического контроля) — Отклонение значения величины, характеризующей состав, структуру, свойства пробы вещества [материала], от значения этой же величины, характеризующей состав, структуру, свойства объекта аналитического контроля в целом. Примечание Погрешность отбора … Справочник технического переводчика
Семантика объекта цифровой топографической карты — часть информации в составе объекта цифровой топографической карты, описывающая сущность и свойства объекта топографической карты. Источник: ОСТ 68 3.1 98. Стандарт отрасли. Карты цифровые топографические. Общие требования (принят и введен в… … Официальная терминология
характеристика объекта прогнозирования — характеристика объекта прогнозирования; отрасл. признак Качественное или количественное отражение какого либо свойства объекта прогнозирования … Политехнический терминологический толковый словарь
паспорт охраняемого объекта — Задокументированные свойства объекта, отражающие его народнохозяйственную значимость, латентность, дислокацию, устойчивость к преступным посягательствам, технологические и эксплуатационные особенности. [РД 25.03.001 2002] Тематики системы охраны… … Справочник технического переводчика
математическая модель объекта измерений — математическая модель объекта измерений: Математическая модель зависимости между физическими величинами, характеризующими свойства объекта измерений. Источник … Словарь-справочник терминов нормативно-технической документации
паспорт охраняемого объекта — 2.25.5 паспорт охраняемого объекта: Задокументированные свойства объекта, отражающие его народнохозяйственную значимость, латентность, дислокацию, устойчивость к преступным посягательствам, технологические и эксплуатационные особенности Источник … Словарь-справочник терминов нормативно-технической документации
Что такое свойства объекта
Кроме обычных методов в языке C# предусмотрены специальные методы доступа, которые называют свойства . Они обеспечивают простой доступ к полям классов и структур, узнать их значение или выполнить их установку.
Определение свойств
Стандартное описание свойства имеет следующий синтаксис:
Вначале определения свойства могут идти различные модификаторы, в частности, модификаторы доступа. Затем указывается тип свойства, после которого идет название свойства. Полное определение свойства содержит два блока: get и set .
В блоке get выполняются действия по получению значения свойства. В этом блоке с помощью оператора return возвращаем некоторое значение.
В блоке set устанавливается значение свойства. В этом блоке с помощью параметра value мы можем получить значение, которое передано свойству.
Блоки get и set еще называются акссесорами или методами доступа (к значению свойства), а также геттером и сеттером.
Здесь в классе Person определено приватное поле name , которая хранит имя пользователя, и есть общедоступное свойство Name . Хотя они имеют практически одинаковое название за исключением регистра, но это не более чем стиль, названия у них могут быть произвольные и не обязательно должны совпадать.
Через это свойство мы можем управлять доступом к переменной name . В свойстве в блоке get возвращаем значение поля:
А в блоке set устанавливаем значение переменной name. Параметр value представляет передаваемое значение, которое передается переменной name.
В программе мы можем обращаться к этому свойству, как к обычному полю. Если мы ему присваиваем какое-нибудь значение, то срабатывает блок set , а передаваемое значение передается в параметр value :
Если мы получаем значение свойства, то срабатывает блок get , который по сути возвращает значение переменной name:
То есть по сути свойство Name ничего не хранит, оно выступает в роли посредника между внешним кодом и переменной name.
Возможно, может возникнуть вопрос, зачем нужны свойства, если мы можем в данной ситуации обходиться обычными полями класса? Но свойства позволяют вложить дополнительную логику, которая может быть необходима при установке или получении значения. Например, нам надо установить проверку по возрасту:
В данном случае переменная age хранит возраст пользователя. Напрямую мы не можем обратиться к этой переменной — только через свойство Age. Причем в блоке set мы устанавливаем значение, если оно соответствует некоторому разумному диапазону. Поэтому при передаче свойству Age значения, которое не входит в этот диапазон, значение переменной не будет изменяться:
Таким образом, свойство позволяет опосредовать и контролировать доступ к данным объекта.
Свойства только для чтения и записи
Блоки set и get не обязательно одновременно должны присутствовать в свойстве. Если свойство определяет только блок get , то такое свойство доступно только для чтения — мы можем получить его значение, но не установить.
И, наоборот, если свойство имеет только блок set , тогда это свойство доступно только для записи — можно только установить значение, но нельзя получить:
Здесь свойство Name доступно только для чтения, поскольку оно имеет только блок get :
Мы можем получить его значение, но НЕ можем установить:
А свойство Age, наоборот, доступно только для записи, поскольку оно имеет только блок set :
Можно установить его значение, но нельзя получить:
Вычисляемые свойства
Свойства необязательно связаны с определенной переменной. Они могут вычисляться на основе различных выражений
В данном случае класс Person имеет свойство Name, которое доступно только для чтения и которое возвращает общее значение на основе значений переменных firstName и lastName.
Модификаторы доступа
Мы можем применять модификаторы доступа не только ко всему свойству, но и к отдельным блокам get и set:
Теперь закрытый блок set мы сможем использовать только в данном классе — в его методах, свойствах, конструкторе, но никак не в другом классе:
При использовании модификаторов в свойствах следует учитывать ряд ограничений:
Модификатор для блока set или get можно установить, если свойство имеет оба блока (и set, и get)
Только один блок set или get может иметь модификатор доступа, но не оба сразу
Модификатор доступа блока set или get должен быть более ограничивающим, чем модификатор доступа свойства. Например, если свойство имеет модификатор public, то блок set/get может иметь только модификаторы protected internal, internal, protected, private protected и private
Автоматические свойства
Свойства управляют доступом к полям класса. Однако что, если у нас с десяток и более полей, то определять каждое поле и писать для него однотипное свойство было бы утомительно. Поэтому в .NET были добавлены автоматические свойства. Они имеют сокращенное объявление:
На самом деле тут также создаются поля для свойств, только их создает не программист в коде, а компилятор автоматически генерирует при компиляции.
В чем преимущество автосвойств, если по сути они просто обращаются к автоматически создаваемой переменной, почему бы напрямую не обратиться к переменной без автосвойств? Дело в том, что в любой момент времени при необходимости мы можем развернуть автосвойство в обычное свойство, добавить в него какую-то определенную логику.
Стоит учитывать, что нельзя создать автоматическое свойство только для записи, как в случае со стандартными свойствами.
Автосвойствам можно присвоить значения по умолчанию (инициализация автосвойств):
И если мы не укажем для объекта Person значения свойств Name и Age, то будут действовать значения по умолчанию.
Автосвойства также могут иметь модификаторы доступа:
Мы можем убрать блок set и сделать автосвойство доступным только для чтения. В этом случае для хранения значения этого свойства для него неявно будет создаваться поле с модификатором readonly, поэтому следует учитывать, что подобные get-свойства можно установить либо из конструктора класса, как в примере выше, либо при инициализации свойства:
Блок init
Начиная с версии C# 9.0 сеттеры в свойствах могут определяться с помощью оператора init (от слова «инициализация» — это есть блок init призван инициализировать свойство). Для установки значений свойств с init можно использовать только инициализатор, либо конструктор, либо при объявлении указать для него значение. После инициализации значений подобных свойств их значения изменить нельзя — они доступны только для чтения. В этом плане init-свойства сближаются со свойствами для чтения. Разница состоит в том, что init-свойства мы также можем установить в инициализаторе (свойства для чтения установить в инициализаторе нельзя). Например:
В данном случае класс Person для свойства Name вместо сеттера использует оператор init . В итоге на строке
предполагается создание объекта с инициализацией всех его свойств. В данном случае свойство Name получит в качестве значения строку «Undefined». Однако поскольку инициализация свойства уже произошла, то на строке
мы получим ошибку.
Как можно установить подобное свойство? Выше продемонстрирован один из способов — установка значения при определении свойства. Второй способ — через конструктор:
Третий способ — через инициализатор:
В принцпе есть еще четвертый способ — установка через другое свойство с модификатором init :
В данном случае в init-свойстве Name разворачивается в полное свойство, которое управляет полем для чтения name . Благодаря этому перед установкой значения свойства мы можем произвести некоторую предобработку. Кроме того, в выражении init устанавливается другое init-свойство — Email, которое для установки значения использует значение свойства Name — из имени получаем значение для электронного адреса.
Причем если при объявлении свойства указано значение, то в конструкторе мы можем его изменить. Значение, установленное в конструкторе, можно изменить в инициализаторе. Однако дальше процесс инициализации заканчивается. И значение не может быть изменено.
Сокращенная запись свойств
Как и методы, мы можем сокращать определения свойств. Поскольку блоки get и set представляют специальные методы, то как и обычные методы, если они содержат одну инструкцию, то мы их можем сократить с помощью оператора => :
Также можно сокращать все свойство в целом:
модификатор required
Модификатор required (добавлен в C# 11) указывает, что поле или свойства с этим модификатором обязательно должны быть инициализированы. Например, в следующем примере мы получим ошибку:
Здесь свойства Name и Age отмечены как обязательные для инициализации с помощью модификатора required , поэтому необходимо использовать инициализатор для их инициализации:
Причем не важно, устанавливаем эти свойства в конструкторе или инициализируем при определении, все равно надо использовать инициализатор для установки их значений. Например, в следующем примере мы получим ошибку: