- •Понятие объектно-ориентированного программирования (ооп). Классы и объекты
- •Классы в Си-шарп. Объявление классов и создание объектов
- •Методы в Си-шарп. Разница между простыми и статическими
- •Конструкторы в Си-шарп. Указатель this
- •Свойства в Си-шарп. Аксессоры get и set. Автоматические свойства
- •Наследование в Си-шарп. Конструктор базового класса
- •Массив указателей на базовый класс в Си-шарп. Операторы is и as
- •Полиморфизм в Си-шарп. Что это такое?
- •Виртуальные методы в Си-шарп. Переопределение методов
- •Абстрактные классы, методы и свойства в Си-шарп
- •Интерфейсы в Си-шарп. Множественное наследование
- •Перегрузка методов в Си-шарп
- •Инкапсуляция в Си-шарп. Модификаторы доступа
- •Перегрузка операторов в Си-шарп
Свойства в Си-шарп. Аксессоры get и set. Автоматические свойства
В этом уроке мы продолжим рассматривать члены классов, и на очереди у нас свойства. Свойство в Си-шарп – это член класса, который предоставляет удобный механизм доступа к полю класса (чтение поля и запись). Свойство представляет собой что-то среднее между полем и методом класса. При использовании свойства, мы обращаемся к нему, как к полю класса, но на самом деле компилятор преобразовывает это обращение к вызову соответствующего неявного метода. Такой метод называется аксессор (accessor). Существует два таких метода: get (для получения данных) и set (для записи). Объявление простого свойства имеет следующую структуру:
[модификатор доступа] [тип] [имя_свойства] { get { // тело аксессора для чтения из поля } set { // тело аксессора для записи в поле } }
Приведу пример использования свойств. Имеется класс Студент, и в нем есть закрытое поле курс, которое не может быть ниже единицы и больше пяти. Для управления доступом к этому полю будет использовано свойство Year:
class Student { private int year; //объявление закрытого поля public int Year //объявление свойства { get // аксессор чтения поля { return year; } set // аксессор записи в поле { if (value < 1) year = 1; else if (value > 5) year = 5; else year = value; } } } class Program { static void Main(string[] args) { Student st1 = new Student(); st1.Year = 0; // записываем в поле, используя аксессор set Console.WriteLine(st1.Year); // читаем поле, используя аксессор get, выведет 1 Console.ReadKey(); } }
Проще говоря, в свойстве реализуются два метода. В теле аксессора getможет быть более сложная логика доступа, но в итоге должно возвращаться значение поля, либо другое значение с помощью оператора return. В аксессоре set же присутствует неявный параметр value, который содержит значение, присваиваемое свойству (в примере выше, при записи, значениеvalue равно «0»). Зачем это нужно? Если, например, мы бы просто сделали поле year открытым и не использовали ни методы, ни свойство для доступа, мы могли бы записать в это поле любое значение, в том числе и некорректное, а так мы можем контролировать чтение и запись. Для контроля доступа мы могли бы здесь использовать простые методы, но для этого нам бы пришлось реализовать два отдельных метода, с разными именами, и при обращении к ним необходимо использовать скобки, что добавляет лишние неудобства. Вот как бы выглядела та же программа с использованием методов (на практике используйте свойства):
class Student { private int year; public int GetYear() { return year; } public void SetYear(int value) { if (value < 1) year = 1; else if (value > 5) year = 5; else year = value; } } class Program { static void Main(string[] args) { Student st1 = new Student(); st1.SetYear(0); Console.WriteLine(st1.GetYear()); Console.ReadKey(); } }
Свойство также может предоставлять доступ только на чтение поля или только на запись. Если, например, нам необходимо закрыть доступ на запись, мы просто не указываем аксессор set. Пример:
class Student { private int year; public Student(int y) // конструктор { year = y; } public int Year { get { return year; } } } class Program { static void Main(string[] args) { Student st1 = new Student(2); Console.WriteLine(st1.Year); // чтение st1.Year = 5; // ошибка, свойство только на чтение Console.ReadKey(); } }
Стоит помнить, что само свойство не определяет место в памяти для хранения поля, и, соответственно, необходимо отдельно объявить поле, доступом к которому будет управлять свойство. Автоматические свойства Автоматическое свойство – это очень простое свойство, которое, в отличии от простого свойства, уже определяет место в памяти (создает неявное поле), но при этом не позволяет создавать логику доступа. Структура объявления Автоматического свойства:
[модификатор доступа] [тип] [имя_свойства] { get; set; }
У таких свойств, у их аксессоров отсутствует тело. Пример использования:
class Student { public int Year { get; set; } } class Program { static void Main(string[] args) { Student st1 = new Student(); st1.Year = 0; Console.WriteLine(st1.Year); Console.ReadKey(); } }
Автоматически реализуемые свойства есть смысл использовать тогда, когда нет необходимости накладывать какие-либо ограничения на возможные значения неявного поля свойства. И тут у вас может возникнуть вопрос, а в чем тогда разница между простыми открытыми полями и автоматическими свойствами. У таких свойств остается возможность делать их только на чтение или только на запись. Для этого уже используется модификатор доступа private перед именем аксессора:
public int Year { private get; set; } // свойство только на запись public int Year { get; private set; } // свойство только на чтение
Домашнее задание Создайте класс Телевизор, объявите в нем поле громкость звука, для доступа к этому полю реализуйте свойство. Громкость может быть в диапазоне от 0 до 100.
