Конструктори и this
Проблем
Кафе за 0 €
Създаваш продукт, както в миналия урок, и попълваш полетата ред по ред. Един ред си забравил:
Product coffee = new Product();coffee.name = "Кафе";coffee.quantity = 2;System.out.println(coffee.name + ": " + coffee.price * coffee.quantity + " €");Кафе: 0.0 €Кафето струва 0 €. Компилаторът не се оплаква: от негова гледна точка цената си има стойност, 0. Колкото повече полета има класът, толкова по-лесно е да пропуснеш едно. А продукт без цена не трябва изобщо да може да съществува.
Идеята
Конструктор: без тези данни няма обект
Класът може да каже какво е нужно, за да се създаде обект от него. За това служи конструкторът: специален метод, който се изпълнява при new.
class Product { public String name; public double price; public int quantity;
public Product(String name, double price, int quantity) { this.name = name; this.price = price; this.quantity = quantity; }}
public class Main { public static void main(String[] args) { Product coffee = new Product("Кафе", 7.50, 2); System.out.println(coffee.name + ": " + coffee.price * coffee.quantity + " €"); }}Кафе: 15.0 €- Конструкторът се казва точно като класа:
Product. - Няма тип на резултата, дори
void. - Параметрите му са данните, без които продукт няма. Те се подават в скобите на
new:new Product("Кафе", 7.50, 2).
Сега няма как да забравиш цената. Ако подадеш два аргумента вместо три, програмата не се компилира.
public Product(String name, double price, int quantity) { this.name = name; this.price = price; this.quantity = quantity;}
Product coffee = new Product("Кафе", 7.50, 2);System.out.println(coffee.name + ": " + coffee.price * coffee.quantity + " €");Стъпка по стъпка, с думи
- new заделя нов обект. Полетата му са със стойности по подразбиране.
- Изпълнява се конструкторът. Аргументите се копират в параметрите му.
- this.name = name: от параметъра в полето на този обект.
- Същото за цената и бройката.
- Конструкторът свърши и параметрите изчезват. В coffee отива стрелка към готовия обект.
- Обектът излиза от new вече попълнен, затова цената не е 0.
Идеята
this: полето на този обект
Вътре в конструктора има две неща с име name: параметърът и полето. Името без нищо пред него е параметърът, защото той е „по-близо“. За полето пишеш this.name.
public Product(String name, double price, int quantity) { this.name = name; this.price = price; this.quantity = quantity;}this е обектът, който се създава в момента. this.name = name; значи „в полето name на този обект запиши параметъра name“.
Може параметрите да се казват другояче (productName), и тогава this не е нужно. Но еднаквите имена са обичайни в Java, защото веднага се вижда кой параметър в кое поле отива.
Пробвай
Намери грешката
Избери реда с грешката.
name = name; записва параметъра в самия него. Полето остава null. Трябва this.name = name;. Компилаторът не дава грешка, затова такъв бъг се хваща трудно.
Идеята
А new Product() от миналия урок?
В миналия урок нямаше конструктор, а new Product() работеше. Ако не напишеш конструктор, компилаторът добавя празен, без параметри. Той се казва конструктор по подразбиране и оставя полетата със стойностите им по подразбиране.
Щом напишеш свой конструктор, празният изчезва:
Product empty = new Product();error: constructor Product in class Product cannot be applied to given types;Това е целта: продукт без име и цена вече не може да се създаде. Ако празен конструктор все пак ти трябва, напиши го сам.
Идеята
Няколко конструктора
Повечето продукти в количката са по един брой. Да пишеш 1 всеки път е досадно.
Можеш да дадеш на класа втори конструктор, без бройката. Той стои до първия:
public Product(String name, double price) { this.name = name; this.price = price; this.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) { this.name = name; this.price = price; this.quantity = 1; }
public Product(String name, double price, int quantity) { this.name = name; this.price = price; this.quantity = quantity; }}
Product bread = new Product("Хляб", 1.20);Product milk = new Product("Мляко", 2.10, 3);System.out.println(bread.quantity + " " + milk.quantity);new Product("Хляб", 1.20) има два аргумента, затова се вика конструкторът с два параметъра. Той записва бройка 1. За млякото са подадени три аргумента и се вика другият конструктор.Пробвай
Как се казва конструкторът?
Какво трябва да пише на празното място?
class Book {
public String title;
public String author;
public (String title, String author) {
this.title = title;
this.author = author;
}
}Book: конструкторът се казва точно като класа, със същата главна буква.Упражнение
Обекти, създадени цели
Реши задачите в редактора си. Всеки клас получава конструктор с параметри за всички полета.
1. Човек. Клас Person с име и възраст. Създай двама души и отпечатай данните им.
Мария, 34 г.Петър, 19 г.2. Животно. Клас Animal с вид и възраст. Създай котка на 3 и куче на 7 години.
Вид: котка, възраст: 3Вид: куче, възраст: 73. Танцова стъпка. Клас DanceMove с име и продължителност в секунди. В урока „Поведение“ стъпката ще се научи да се „изпълнява“.
moonwalk: 5 сек.Още задачи
- Книга с конструктор. Препиши
Bookот миналия урок с конструкторBook(title, author). Колко реда спести в main? -
Продукт с два конструктора.
Productс два конструктора, както в урока. Направи масив{ new Product("Хляб", 1.20, 2), new Product("Кафе", 7.50) }и отпечатай името и бройката на всеки: „Хляб x2“, „Кафе x1“. После накарай по-краткия конструктор да вика по-дългия. - Резервация. Клас
Bookingс име на госта, брой нощувки и цена за нощувка. Отпечатай колко струва престоят: за 3 нощувки по 85 € това е 255 €.
Тест