Урок 3. Свойства класса C#
Третий урок в учебнике по объектно-ориентированному программированию на C# расширяет предыдущее создание простых классов, вводя свойства. Свойства класса позволяют экземплярам объектов иметь состояние, при котором каждый объект управляет своими собственными данными.
Добавление состояния
На предыдущем уроке я объяснил основной синтаксис и процесс создания класса, который имеет методы как часть своего открытого интерфейса. Это позволяет создавать простые классы с поведением, но без состояния. Состояние объекта описывает его индивидуальные данные или уникальную конфигурацию. В примере объекта автомобиля методы позволяют нам ускоряться или замедляться, но состояние, описанное в свойствах, позволяет нам определить фактическую скорость и описать один объект автомобиля как красный, а другой как синий. Эта информация создает реальную дифференциацию между двумя объектами.
В этой статье мы создадим новый класс для представления формы прямоугольника. Этот класс определяет четыре свойства: высоту, ширину, площадь и периметр прямоугольника. Для начала создайте новое консольное приложение и добавьте новый класс с именем "Rectangle".
Добавление свойства
Создание переменной уровня класса
Во многих случаях информация, которая становится общедоступной через свойство, хранится непосредственно в объекте в виде переменной. Эта переменная имеет область видимости, которая делает ее видимой для всего класса. Однако это не всегда так, поскольку информация может храниться в базе данных или другом внешнем источнике или может быть рассчитана, а не сохранена. В примере класса в этой статье два значения свойств будут храниться в переменных и два будут вычислены.
Чтобы определить переменную области действия класса, объявление выполняется в блоке кода класса, но вне каких-либо методов или свойств. Хотя это и не обязательно, полезно предварить объявление переменной ключевым словом private, чтобы сделать код понятным и легким для чтения. Используя этот синтаксис, мы можем добавить две целочисленные переменные в класс Rectangle для хранения высоты и ширины.
class Rectangle{ private int _width; private int _height;}Примечание: использование нижнего регистра верблюда и префикса подчеркивания ( _ ) является одним из стандартов именования переменных уровня класса. Это полезная, хотя и не обязательная конвенция.
Свойства
Добавление свойства в класс аналогично добавлению переменной. Фактически, можно создать элементарное свойство, добавив переменную в область видимости класса и просто объявив ее как public вместо private. Это фактически создает общественное поле. Однако это нецелесообразно, так как это означает, что класс не будет иметь никакого контроля над значениями, заданными для свойств, и некоторые стандартные функции .NET будут потеряны. Чтобы избежать этих проблем свойство объявляется с блоком кода следующим образом:
public int Width{}После объявления функциональность должна быть добавлена к свойству. Это достигается с помощью методов доступа GET и set. Они создают два блока кода, которые управляют тем, как значение свойства извлекается или вычисляется при запросе (метод доступа get) и как значение свойства проверяется, обрабатывается и сохраняется при назначении значения (метод доступа set). Два метода доступа добавляются к свойству с помощью ключевых слов get и set, каждый со своим собственным блоком кода:
public int Width{ get{ } set{ }}Чтобы завершить метод Width, теперь нам нужно добавить код, который обрабатывает получение и настройку свойств. Это относительно просто для метода доступа get. Когда значение свойства запрашивается, мы просто возвращаем значение из переменной уровня класса. Для этого мы можем использовать ключевое слово return с тем же синтаксисом, что и для любого функционального метода.
public int Width{ get{ return _width; } set{ }}При использовании метода доступа set значение, которое внешний объект присваивает свойству, передается как переменная с именем "value". Это можно рассматривать как сходство с параметром метода, даже если его имя скрыто.
Для свойства width, мы будем проверять значение перед сохранением. Если значение отрицательное или больше ста, будет выдано исключение и свойство останется неизменным. Это возможно благодаря правильному использованию методов доступа get и set. Если бы простая открытая переменная была создана, как описано выше, этот уровень управления был бы недоступен.
public int Width{ get{ return _width; } set{ if (value < 0 || value > 100) { throw new OverflowException(); } _width = value; }}Прежде чем опробовать новое свойство, давайте добавим второе свойство для высоты. Применяются те же правила проверки:
public int Height{ get{ return _height; } set{ if (value < 0 || value > 100) { throw new OverflowException(); } _height = value; }}Использование свойств
Доступ к свойствам создаваемых объектов осуществляется с помощью имени объекта, за которым следует оператор доступа к элементу (.) и имя свойства. Свойство может быть прочитано и записано с использованием аналогичного синтаксиса, как для стандартной переменной. Чтобы продемонстрировать это, рассмотрим следующий пример кода, добавленного к основному методу программы. Он создает два объекта на основе класса Rectangle и присваивает и считывает их свойства по отдельности. При попытке присвоить прямоугольнику недопустимую высоту код проверки создает исключение.
static void Main(string[] args){ Rectangle rect = new Rectangle(); rect.Width = 50; rect.Height = 25; Rectangle square = new Rectangle(); square.Height = square.Width = 40; Console.WriteLine(rect.Height); // "25" Console.WriteLine(square.Width); // "40" rect.Height = 125; // выдает исключение проверки.}Примечание: пример кода демонстрирует как инкапсуляцию, так и состояние. Состояние двух прямоугольников хранится внутренне и независимо, а детали реализации свойств скрыты от программы. Если в будущем нам потребуется переместить данные из частных переменных в XML-файл или базу данных, то основной метод изменять не потребуется.
Свойства только для чтения и записи
Свойства Width и Height являются примерами свойств read-write, поскольку информация, содержащаяся в них, может быть как прочитана, так и записана. Иногда вам понадобятся свойства только для чтения или даже только для записи. Их легко создать, просто не указывая методы доступа, которые не требуются.
Теперь мы можем добавить свойства только для чтения для области и периметра прямоугольника с опущенными способами доступа набора. Эти свойства вычисляются из существующих переменных уровня класса, поэтому не требуют прямого внутреннего хранилища. Код выглядит следующим образом:
public int Area{ get{ return _height * _width; }} public int Perimeter{ get{ return 2 * (_height + _width);Новые свойства только для чтения могут быть прочитаны с использованием того же синтаксиса, что и свойства чтения и записи. Проверьте это, изменив основной метод программы:
static void Main(string[] args){ Rectangle rect = new Rectangle(); rect.Width = 8; rect.Height = 12; Console.WriteLine(rect.Area); // "96" Console.WriteLine(rect.Perimeter); // "40"}Внутреннее использование свойства
В примере свойства площади и периметра вычисляются с использованием переменных уровня класса, содержащих фактические значения. Это не всегда возможно или действительно целесообразно, особенно если свойство включает в себя процесс вычисления или проверки. Вместо дублирования кода для вычисления или проверки, свойство может быть доступно по имени. Поэтому мы могли бы настроить свойство Area следующим образом:
public int Area{ get{ return Height * Width; }}В этой обновленной версии свойства Area источник значений высоты и ширины был отделен от внутренних переменных. Если свойства Height и Width будут изменены в будущем для извлечения их значений из базы данных, никаких изменений в свойстве Area не потребуется.
Ключевое слово this
Последнее ключевое слово для рассмотрения - "this". Ключевое слово "this" может использоваться в коде класса для ссылки на текущий экземпляр объекта. Для свойств это редко требуется, если только плохое именование переменных не привело к скрытию имени свойства. В следующем примере метод сравнивает область текущего объекта со значением области, переданным в качестве параметра. Для доступа к имени свойства используется ключевое слово "this", так как параметр метода был неправильно назван и таким образом скрывает свойство:
public bool AreaTheSame(int area){ if (this.Area == area){ return true; } else{ return false; }}Примечание: было бы более уместно переименовать параметр метода в приведенной выше ситуации.
Ключевое слово "this" имеет и другое применение. Если вызывается метод и текущий объект должен быть передан этому методу, установка параметра "this" приводит к желаемому результату. Например:
floorShape.Set(this);
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.