Към съдържанието
wannacode

Конструктори и this

Проблем

Кафе за 0 €

Създаваш продукт, както в миналия урок, и попълваш полетата ред по ред. Един ред си забравил:

Product coffee = new Product();
coffee.Name = "Кафе";
coffee.Quantity = 2;
Console.WriteLine(coffee.Name + ": " + coffee.Price * coffee.Quantity + " €");
Изход
Кафе: 0 €

Кафето струва 0 €. Компилаторът не се оплаква: от негова гледна точка цената си има стойност, 0. Колкото повече полета има класът, толкова по-лесно е да пропуснеш едно. А продукт без цена не трябва изобщо да може да съществува.

Идеята

Конструктор: без тези данни няма обект

Класът може да каже какво е нужно, за да се създаде обект от него. За това служи конструкторът: специален метод, който се изпълнява при new.

Program.cs
class Product
{
public string Name;
public double Price;
public int Quantity;
public Product(string name, double price, int quantity)
{
Name = name;
Price = price;
Quantity = quantity;
}
}
class Program
{
static void Main()
{
Product coffee = new Product("Кафе", 7.50, 2);
Console.WriteLine(coffee.Name + ": " + coffee.Price * coffee.Quantity + " €");
}
}
Изход
Кафе: 15 €
  • Конструкторът се казва точно като класа: Product.
  • Няма тип на резултата, дори void.
  • Параметрите му са данните, без които продукт няма. Те се подават в скобите на new: new Product("Кафе", 7.50, 2).

Сега няма как да забравиш цената. Ако подадеш два аргумента вместо три, програмата не се компилира.

public Product(string name, double price, int quantity)
{
Name = name;
Price = price;
Quantity = quantity;
}
Product coffee = new Product("Кафе", 7.50, 2);
Console.WriteLine(coffee.Name + ": " + coffee.Price * coffee.Quantity + " €");
Стъпка по стъпка, с думи
  1. new заделя нов обект. Полетата му са със стойности по подразбиране.
  2. Изпълнява се конструкторът. Аргументите се копират в параметрите му.
  3. Name = name: от параметъра в полето на обекта.
  4. Същото за цената и бройката.
  5. Конструкторът свърши и параметрите изчезват. В coffee отива стрелка към готовия обект.
  6. Обектът излиза от new вече попълнен, затова цената не е 0.

Идеята

this: полето на този обект

В C# полето е Name, а параметърът е name. Имената се различават по главната буква, затова Name = name; е ясно: отляво е полето, отдясно е параметърът.

Същото може да се напише и с this: обектът, който се създава в момента. this.Name е „полето Name на този обект“:

public Product(string name, double price, int quantity)
{
this.Name = name;
this.Price = price;
this.Quantity = quantity;
}

Тук this не е задължително. Ще ти трябва, когато полето и параметърът се казват еднакво. Такива полета (с малка буква) ще видиш в урока „Капсулация“: там this.balance = balance; е единственият начин да стигнеш до полето.

Пробвай

Намери грешката

Програмата трябва да отпечата „Чай: 3.2 €“. Цената излиза, а името не. На кой ред е грешката?

Избери реда с грешката.

Идеята

А new Product() от миналия урок?

В миналия урок нямаше конструктор, а new Product() работеше. Ако не напишеш конструктор, компилаторът добавя празен, без параметри. Той се казва конструктор по подразбиране и оставя полетата със стойностите им по подразбиране.

Щом напишеш свой конструктор, празният изчезва:

Product empty = new Product();
Грешка при компилиране
error CS7036: There is no argument given that corresponds to the required parameter 'name' of 'Product.Product(string, double, int)'

Това е целта: продукт без име и цена вече не може да се създаде. Ако празен конструктор все пак ти трябва, напиши го сам.

Идеята

Няколко конструктора

Повечето продукти в количката са по един брой. Да пишеш 1 всеки път е досадно.

Можеш да дадеш на класа втори конструктор, без бройката. Той стои до първия:

public Product(string name, double price)
{
Name = name;
Price = price;
Quantity = 1;
}

Това е претоварването от модул „Методи“: едно име, различни параметри. При new компилаторът избира конструктора по аргументите.

По-точно, за любопитните

Двата конструктора повтарят едни и същи редове. Вместо това по-краткият може да извика по-дългия:

public Product(string name, double price)
: this(name, price, 1)
{
}

: this(...) след скобите вика друг конструктор на същия клас, преди да се изпълни тялото. Тук тялото е празно.

Така, ако утре добавиш проверка на цената, я пишеш само в един конструктор.

Пробвай

Кой конструктор?

Какво ще отпечата програмата?

class Product
{
public string Name;
public double Price;
public int Quantity;
public Product(string name, double price)
{
Name = name;
Price = price;
Quantity = 1;
}
public Product(string name, double price, int quantity)
{
Name = name;
Price = price;
Quantity = quantity;
}
}
Product bread = new Product("Хляб", 1.20);
Product milk = new Product("Мляко", 2.10, 3);
Console.WriteLine(bread.Quantity + " " + milk.Quantity);
Отговор

Пробвай

Как се казва конструкторът?

Какво трябва да пише на празното място?

class Book
{
    public string Title;
    public string Author;

    public (string title, string author)
    {
        Title = title;
        Author = author;
    }
}

Упражнение

Обекти, създадени цели

Реши задачите в редактора си. Всеки клас получава конструктор с параметри за всички полета.

1. Човек. Клас Person с име и възраст. Създай двама души и отпечатай данните им.

Изход
Мария, 34 г.
Петър, 19 г.

2. Животно. Клас Animal с вид и възраст. Създай котка на 3 и куче на 7 години.

Изход
Вид: котка, възраст: 3
Вид: куче, възраст: 7

3. Танцова стъпка. Клас DanceMove с име и продължителност в секунди. В урока „Поведение“ стъпката ще се научи да се „изпълнява“.

Изход
moonwalk: 5 сек.

Още задачи

  • Книга с конструктор. Препиши Book от миналия урок с конструктор Book(title, author). Колко реда спести в Main?
  • Продукт с два конструктора. Product с два конструктора, както в урока. Направи масив { new Product("Хляб", 1.20, 2), new Product("Кафе", 7.50) } и отпечатай името и бройката на всеки: „Хляб x2“, „Кафе x1“. После накарай по-краткия конструктор да вика по-дългия.
  • Резервация. Клас Booking с име на госта, брой нощувки и цена за нощувка. Отпечатай колко струва престоят: за 3 нощувки по 85 € това е 255 €.

Тест

Провери се

1. Кога се изпълнява конструкторът?
2. Какъв тип на резултата се пише пред името на конструктора?
3. В класа има само конструктор Product(name, price). Какво става с new Product()?
4. Какво е this в конструктора?
5. В класа има два конструктора: с име и цена и с име, цена и бройка. Как се казва това?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·