Свой тип
Проблем
Цените се разбъркаха
Пишеш количката на онлайн магазин. Всеки продукт има име и цена, затова ги пазиш в два масива: на индекс 0 са името и цената на първия продукт, на индекс 1 на втория.
Искаш най-скъпото най-отпред и разменяш цените:
string[] names = { "Хляб", "Мляко", "Кафе" };double[] prices = { 1.20, 2.10, 7.50 };
// Най-скъпото отпред: разменяме първата и третата цена.double temp = prices[0];prices[0] = prices[2];prices[2] = temp;
for (int i = 0; i < names.Length; i++){ Console.WriteLine(names[i] + ": " + prices[i] + " €");}Хляб: 7.5 €Мляко: 2.1 €Кафе: 1.2 €Хлябът вече струва 7,50 €. Цените са разменени, а имената не са. Двата масива трябва да се пипат винаги заедно, но нищо не те задължава. Добавиш ли трети масив с бройките, ще трябва да помниш три.
Идеята
Един продукт, едно място
Името и цената не са отделни неща. Те са части от един продукт. Искаме тип „продукт“, както има тип int за число и string за текст.
Такъв тип си правиш сам. Той се казва клас:
class Product{ public string Name; public double Price; public int Quantity;}Променливите в класа са неговите полета. Всеки продукт ще има свое име, своя цена и своя бройка.
Класът е само описание: „всеки продукт има име, цена и бройка“. Продукт още няма.
public значи, че полетата се виждат и отвън, от Main. Без него C# не ги показва навън. Защо е така, ще видим в урока „Капсулация“. Имената на публичните полета в C# започват с главна буква: Name, Price.
Идеята
new: от описанието към продукт
Конкретен продукт по класа се създава с new. Той се казва обект. До полетата му стигаш с точка:
class Product{ public string Name; public double Price; public int Quantity;}
class Program{ static void Main() { Product bread = new Product(); bread.Name = "Хляб"; bread.Price = 1.20; bread.Quantity = 2;
Product coffee = new Product(); coffee.Name = "Кафе"; coffee.Price = 7.50; coffee.Quantity = 1;
Console.WriteLine(bread.Name + ": " + bread.Price * bread.Quantity + " €"); Console.WriteLine(coffee.Name + ": " + coffee.Price * coffee.Quantity + " €"); }}Хляб: 2.4 €Кафе: 7.5 €- Класът стои извън class Program, над него. Във файла може да има няколко класа.
Product breadе променлива от типProduct, кактоint countе от типint.new Product()създава нов обект. Всеки обект има свои полета: хлябът и кафето не си пречат.bread.Priceе „цената на хляба“. Чете се и се записва като обикновена променлива.
Сега името и цената на продукта са на едно място. Разместиш ли продукта, те вървят заедно.
Пробвай
Нищо не е попълнено
Ако създадеш продукт и не попълниш нищо, какво има в полетата?
Какво ще отпечата програмата?
Product item = new Product();Console.WriteLine(item.Name);Console.WriteLine(item.Price);Console.WriteLine(item.Quantity);Полетата на нов обект винаги имат стойност по подразбиране: 0 за числата, false за булевите и null за текста. null значи „нищо“. Console.WriteLine печата null като празен ред. Локалните променливи в Main нямат такава стойност. Там компилаторът иска да ги попълниш, преди да ги четеш.
Пробвай
Кое липсва?
Какво трябва да пише на празното място, за да има нов продукт?
Product milk = Product();
milk.Name = "Мляко";
milk.Price = 2.10;new: само той създава обект. Без него има само променлива, която още не сочи към нищо.Виж го
Променливата сочи към обекта
Искаш промоция на кафето и правиш „копие“, за да му смениш цената:
Product coffee = new Product();coffee.Price = 10;Product sale = coffee;sale.Price = 8;Console.WriteLine(coffee.Price); // 8Стъпка по стъпка, с думи
- new прави обекта: полетата му са с начални стойности. В coffee отива стрелка към него.
- По стрелката от coffee: цената на обекта става 10.
- sale = coffee копира стрелката, не обекта. Две стрелки, един обект.
- По стрелката от sale: цената в същия обект става 8.
- coffee сочи същия обект, затова печата 8.
Цената на кафето също стана 8. Причината е, че променливата coffee не е самият обект. Обектът стои отделно в паметта, а coffee пази къде е той: стрелка към обекта. Такава променлива се казва референция.
sale = coffee копира стрелката, а не обекта. Сега две стрелки сочат един обект, затова промяната през sale се вижда и през coffee.
Същото видя в урока за масивите: sale = prices даде второ име на същия масив. Масивът също е обект.
Идеята
Отстъпката вече работи
В модул „Методи“ отстъпката не се получи: методът получи копие на цената, промени копието и то изчезна. С обект е друго:
static void Discount(Product p, double percent){ p.Price = p.Price * (100 - percent) / 100;}
Product coffee = new Product();coffee.Price = 10;Discount(coffee, 10);Console.WriteLine(coffee.Price);9Параметърът пак е копие, но копие на стрелката. Тя сочи същия обект, затова промяната на p.Price остава и след метода.
По-точно, за любопитните
Ако методът сложи в параметъра нов обект, той мести само своето копие на стрелката. Обектът отвън не се променя:
static void Reset(Product p){ p = new Product(); p.Price = 0;}
Product coffee = new Product();coffee.Price = 10;Reset(coffee);Console.WriteLine(coffee.Price);10ref и out), а при обектите стойността е референцията.Идеята
null: стрелка за никъде
Променлива от тип клас може да не сочи към нищо. Тогава в нея е null. Ако опиташ да прочетеш поле през нея, няма обект, от който да го прочетеш:
Product gift = null;Console.WriteLine(gift.Name);Програмата се компилира, но спира с грешка, когато стигне до реда:
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.Това е най-честата грешка с обекти. Какво е „exception“ и как се хваща, ще видим в модул „Грешки и изключения“.
Внимавай с масивите от обекти. new Product[3] прави три места за стрелки, а не три продукта. Всяко е null, докато не сложиш там new Product():
Product[] cart = new Product[3];Console.WriteLine(cart[0] == null);cart[0] = new Product();cart[0].Name = "Хляб";Console.WriteLine(cart[0].Name);TrueХлябПробвай
Намери грешката
Програмата трябва да отпечата „Хляб“ и „Мляко“. Вместо това печата „Мляко“ два пъти. На кой ред е грешката?
Избери реда с грешката.
Product milk = bread; не прави нов продукт. Сега milk и bread сочат един и същ обект, и името „Мляко“ замества „Хляб“. Поправката е Product milk = new Product();.
Упражнение
Твоите класове
1. Книга. Клас Book с полета за заглавие и автор. Създай две книги и ги отпечатай.
Под игото от Иван ВазовТютюн от Димитър Димов2. Кола. Клас SimpleCar с поле за скоростта. Създай кола (скоростта ѝ е 0), увеличи скоростта с 10 и я отпечатай. В урока „Поведение“ това ще стане метод на колата.
Скорост след ускоряване: 103. Количката. Количката от първата карта, този път с масив от три обекта Product: хляб 1,20 € (2 броя), мляко 2,10 € (1 брой), кафе 7,50 € (1 брой). Отпечатай сумата за всеки ред и общата сума. Не забравяй, че след new Product[3] в масива още няма продукти.
Хляб x2: 2.4 €Мляко x1: 2.1 €Кафе x1: 7.5 €Общо: 12 €4. Най-скъпото отпред. Подреди същата количка по цена, от най-скъпото към най-евтиното, с метода на мехурчето от урока за масивите. Този път разменяш цели продукти, затова името и цената вървят заедно.
Кафе: 7.5 €Мляко: 2.1 €Хляб: 1.2 €Още задачи
- Ученик. Клас
Studentс име и три оценки (три полета). Създай двама ученици и отпечатай средния успех на всеки. - Една книга, две имена. Създай книга, запиши я в две променливи и смени заглавието през втората. Отпечатай заглавието през първата. Обясни с думи защо е така.
Тест