Перейти к содержимому
Теория · Классы и объекты · урок 1 из 11

Класс и объект

Чему вы научитесь

Чему вы научитесь:

  • описывать класс с полями и методами и создавать по нему объекты через new;
  • задавать объекту начальные значения конструктором и закрывать его поля свойствами;
  • отличать поля каждого объекта от статических полей, общих для всего класса;
  • объяснять, почему после House b = a; у одного дома два имени.
Чертёж House и два дома по нему: красный двухэтажный a и синий одноэтажный b

Представьте чертёж дома. На нём указано, что у дома есть цвет стен и число этажей, но сам чертёж — не дом: жить в нём нельзя. По одному чертежу строят сколько угодно домов. У каждого дома свой цвет: один выкрасили в красный, другой в синий, и покраска одного не трогает соседа.

В C# такой чертёж называется классом. Класс описывает новый тип: какие данные хранит каждое его значение и что с этими данными можно делать. Дом, построенный по чертежу, называется объектом: это одно значение этого типа. Объект ещё называют экземпляром класса.

Зачем нужен класс? Без него данные двух домов лежат в отдельных переменных: color1, floors1, color2, floors2. Ничто в программе не говорит, что color1 и floors1 относятся к одному дому. Класс собирает данные дома и действия с ними в одно целое:

C#
House a = new House();
a.Color = "red";
a.Floors = 2;
House b = new House();
b.Color = "blue";
b.Floors = 1;
a.Describe(); // red, 2
b.Describe(); // blue, 1

class House
{
    public string Color = "";
    public int Floors;
    public void Describe() => Console.WriteLine(Color + ", " + Floors);
}

Давайте разберём программу по строкам:

  1. class House { … } объявляет класс — чертёж, который сам по себе не строит ни одного дома.
  2. public string Color = ""; и public int Floors; — данные, которые будут у каждого дома.
  3. public void Describe() — метод класса: он печатает цвет и число этажей того дома, для которого его вызвали.
  4. House a = new House(); строит по чертежу дом и даёт ему имя a, а House b = new House(); строит второй, отдельный дом.
  5. a.Color = "red"; красит стены дома a: точка после имени открывает данные конкретного дома.
  6. a.Describe() печатает red, 2, а b.Describe() — blue, 1. Метод один, а дома разные.

Класс — это тип

Классом пользуются так же, как типами int или string. Переменную для дома объявляют как обычно: сначала тип, потом имя. Про такую переменную запомните две вещи:

  • House a = new House(); можно записать короче: var a = new House();. Тип виден справа.
  • Как и переменная массива, a хранит ссылку на объект, а не сам объект.

Поля

Поле — переменная, объявленная внутри класса. У каждого объекта свой набор полей: у дома a свой Color, у дома b свой. Разберём объявление public string Color = ""; по частям:

  • public открывает поле для кода снаружи класса, в том числе для инструкций верхнего уровня;
  • string — тип поля;
  • Color — имя, по соглашению с большой буквы, как у всех открытых полей;
  • = "" — значение, с которым поле появляется в каждом новом доме.

Поле без начального значения получает значение по умолчанию, как элемент нового массива: число — 0, bool — false. Поэтому у нового дома Floors равно 0. Строковому полю значение дают сразу, хотя бы пустую строку "": без него в поле нет строки, и компилятор выдаёт предупреждение CS8618.

Поле принадлежит объекту, а не классу. Строка House.Color = "red"; не скомпилируется (CS0120): у чертежа нет цвета, красят конкретный дом.

Методы объекта

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

C#
House a = new House();
House b = new House();
a.Paint("red");
b.Paint("blue");
a.Paint("green");
Console.WriteLine(a.Color); // green
Console.WriteLine(b.Color); // blue

class House
{
    public string Color = "";

    public void Paint(string color) => this.Color = color;
}

Разберём вызовы Paint:

  1. a.Paint("red") выполняет тело метода для дома a и красит его стены.
  2. b.Paint("blue") выполняет то же тело, но теперь для дома b.
  3. a.Paint("green") перекрашивает a, а b остаётся синим.

Слово this внутри метода означает объект, для которого метод вызвали. Строка this.Color = color; значит то же, что Color = color;, и обычно this не пишут. Оно нужно, когда параметр назван так же, как поле: без this имя означало бы параметр.

Метод класса видит свои параметры и поля своего объекта, а переменные инструкций верхнего уровня не видит. Метод, объявленный прямо среди этих инструкций, их видит.

Где чертёж и класс расходятся

Строители могут отступить от чертежа и пристроить к дому гараж. Объект так не умеет: у него есть только поля и методы, объявленные в классе. Поэтому a.Garage = true; не скомпилируется (CS1061).

Чем класс отличается от объекта

Об этом часто спрашивают на собеседовании. Ответ из двух частей:

  • класс — описание типа в коде: какие поля и методы будут у объектов;
  • объект — экземпляр, построенный по классу через new, со своими значениями полей.

Частая ошибка

Класс объявили в начале файла, над инструкциями:

C#
class House
{
    public string Color = "";
}

House a = new House(); // ✗
Console.WriteLine(a.Color);
TEXT
error CS8803: Top-level statements must precede namespace and type declarations.

Программа не компилируется. Это правило из темы о первой программе: инструкции верхнего уровня идут первыми, а объявления классов — после них. Компилятор указывает на первую инструкцию ниже класса. Перенесите класс в конец файла.

Главное

  • Класс — чертёж нового типа: он объявляет поля и методы, а объекты строят по нему через new.
  • У каждого объекта свои поля: если перекрасить один дом, другие не изменятся.
  • Метод класса работает с полями того объекта, для которого его вызвали; внутри метода этот объект называется this.