4-bob. Obyektga yo‘naltirilgan dasturlash
Sinflar va ob'ektlar
Dart ob'ektga yo'naltirilgan tildir va biz Dart dasturida boshqaradigan har bir qiymat ob'ektdir.
Ob'ekt ba'zi sinfning namunasini, sinf esa ob'ektning shablonini yoki tavsifini ifodalaydi. Quyidagi o'xshashlikni ham chizishingiz mumkin. Har birimiz inson haqida qandaydir tasavvurga egamiz - ikki qo'li, ikki oyog'i, boshi, tanasi va boshqalar. Ba'zi bir naqsh mavjud - bu naqshni sinf deb atash mumkin. Haqiqatan ham mavjud bo'lgan shaxs (aslida bu sinfning namunasi) bu sinfning ob'ektidir.
Sinf class kalit so'zi yordamida aniqlanadi:
Bu erda Person klassi aniqlanadi. Sinf nomidan keyin jingalak qavslar mavjud bo'lib, ular orasiga sinf tanasi - ya'ni uning maydonlari va usullari joylashtiriladi.
Har qanday ob'ekt ikkita asosiy xususiyatga ega bo'lishi mumkin: holat - ob'ekt saqlaydigan ba'zi ma'lumotlar va xatti-harakatlar - ob'ekt bajarishi mumkin bo'lgan harakatlar.
Ob'ekt holatini sinfda saqlash uchun maydonlar yoki sinf o'zgaruvchilari ishlatiladi. Usullar sinfdagi ob'ektning harakatini aniqlash uchun ishlatiladi. Masalan, shaxsni ifodalovchi Person sinfi quyidagi ta'rifga ega bo'lishi mumkin:
1
2
3
4
5
6
7
8
|
class Person{
String name = "undefined"; // имя
int age = 0; // возраст
void display(){
print("Name: $name Age: $age");
}
}
|
Person klassi ikkita maydonni belgilaydi: ism shaxsning ismini, yoshi esa uning yoshini bildiradi. Va displey usuli ham aniqlangan, u hech narsa qaytarmaydi va faqat bu ma'lumotlarni konsolga chop etadi.
Shuni yodda tutish kerakki, o'zgaruvchilar nomi va yoshi null bo'lmagan String va int turlarini ifodalaganligi sababli, biz ushbu o'zgaruvchilarni boshlang'ich qiymatlari bilan ta'minlashimiz kerak. Yoki null bo'ladigan turlardan foydalanishimiz mumkin, keyin boshlang'ich qiymatlarni kiritish shart emas:
1
2
3
4
5
6
7
8
|
class Person{
String? name; // имя
int? age; // возраст
void display(){
print("Name: $name Age: $age");
}
}
|
Endi biz ushbu sinfdan foydalanamiz. Buning uchun biz quyidagi dasturni belgilaymiz:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
void main (){
Person tom;
}
class Person{
String name = "undefined"; // имя
int age = 0; // возраст
void display(){
print("Name: $name Age: $age");
}
}
|
Sinf yangi turni ifodalaydi, shuning uchun biz berilgan turni ifodalovchi o'zgaruvchilarni aniqlashimiz mumkin. Demak, bu yerda asosiy funksiyada Person sinfini ifodalovchi tom o‘zgaruvchisi aniqlanadi. Ammo hozircha bu o'zgaruvchi hech qanday ob'ektga ishora qilmaydi va u sukut bo'yicha null. Umuman olganda, biz uni hali ishlata olmaymiz, shuning uchun avval Person sinfining ob'ektini yaratishingiz kerak.
Konstruktorlar
Oddiy usullardan tashqari, sinflar konstruktorlar deb ataladigan maxsus usullarni belgilashi mumkin. Konstruktorlar ushbu sinfning yangi ob'ekti yaratilganda chaqiriladi. Konstruktorlar obyektni ishga tushirishni amalga oshiradilar.
Agar sinfda konstruktor aniqlanmagan bo'lsa, bu sinf uchun avtomatik ravishda parametrsiz konstruktor yaratiladi.
Yuqorida tavsiflangan Person sinfida konstruktorlar mavjud emas. Shuning uchun, u uchun avtomatik ravishda standart konstruktor yaratiladi, biz undan Person ob'ektini yaratishda foydalanishimiz mumkin. Xususan, bitta ob'ekt yarataylik:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
void main (){
Person tom = Person();
tom.display();
// изменяем имя и возраст
tom.name = "Tom";
tom.age = 35;
tom.display();
}
class Person{
String name = "undefined";
int age = 0;
void display(){
print("Name: $name Age: $age");
}
}
|
Shaxs () ifodasi Shaxs ob'ektini yaratish uchun ishlatiladi. Dartning eski versiyalarida konstruktorni chaqirish uchun yangi operator ham ishlatilgan: Shaxs tom = new Person () ;. Ammo Dartning so'nggi versiyalarida yangi operatorni o'tkazib yuborish mumkin.
Standart konstruktor hech qanday parametrlarni olmaydi. Natijada, ushbu ifoda bajarilgandan so'ng, xotirada Person ob'ektining barcha ma'lumotlari saqlanadigan bo'lim ajratiladi. Va tom o'zgaruvchisi yaratilgan ob'ektga havola oladi.
Agar konstruktor ob'ekt o'zgaruvchilari qiymatlarini ishga tushirmasa, ular standart qiymatlarni, ya'ni null qiymatini oladi (ya'ni, aslida hech qanday qiymat yo'q).
Ob'ektni yaratgandan so'ng, biz tom o'zgaruvchisi orqali Person ob'ektining o'zgaruvchilari va usullariga kirishimiz mumkin. Buning uchun nuqta (.) operatoridan foydalaning - ya'ni nuqta orqali maydon yoki usul nomini belgilang: tom.name. Masalan, siz maydon qiymatlarini belgilashingiz yoki olishingiz mumkin: tom.name = "Tom".
Natijada, biz konsolda ko'ramiz:
Name: undefined Age: 0
Name: Tom Age: 35
Agar ob'ektni yaratishda ba'zi bir mantiq amalga oshirilishi kerak bo'lsa, masalan, sinfning maydonlari muayyan qiymatlarni olishi uchun, siz sinfda o'zingizning konstruktorlaringizni belgilashingiz mumkin. Masalan:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
void main (){
Person sam = Person("Sam", 25);
sam.display();
}
class Person{
String name = "undefined";
int age = 0;
Person(String n, int a)
{
name = n;
age = a;
}
void display(){
print("Name: $name Age: $age");
}
}
|
Endi sinfda ikkita parametrni qabul qiluvchi va ob'ekt maydonlarining qiymatlarini o'rnatish uchun foydalanadigan konstruktor mavjud.
Dasturning konsol chiqishi:
Name: Sam Age: 25
Shuni yodda tutish kerakki, agar biz yuqoridagi holatda bo'lgani kabi sinfda o'z konstruktorlarimizni aniqlasak, u holda biz standart konstruktordan foydalana olmaymiz.
null va sinflar
Barcha o'rnatilgan turlar singari, sinflar sukut bo'yicha null bo'lmagan turni ifodalaydi. Agar bizga sinf ob'ekti null qiymatni saqlashi kerak bo'lsa, biz null bo'ladigan sinfdan foydalanishimiz mumkin, ya'ni tur ta'rifiga? operatorini qo'shishimiz mumkin:
1
2
3
4
5
6
7
|
void main (){
Person? sam;
print(sam); // null - sam допускает значение null
Person tom;
// print(tom); // ! Ошибка, tom не может принимать null
}
|
Null bo'lishi mumkin bo'lmagan boshqa turdagi o'zgaruvchilarda bo'lgani kabi, chop etish (tom) chaqiruvida, o'zgaruvchini ishlatishdan oldin ishga tushirish kerak.
Shu bilan birga, null bo'lgan sinflardan foydalanganda biz quyidagi vaziyatga tushishimiz mumkin. Yuqorida aytib o'tilganidek, nuqta (.) operatori ob'ektning maydonlari va usullariga murojaat qilish uchun ishlatiladi, undan keyin maydon / usul nomi keladi. Biroq, biz bilganimizdek, null bo'ladigan sinflarning o'zgaruvchilariga qiymat berilmagan bo'lsa, ular sukut bo'yicha null bo'ladi. Buni hisobga olish kerak. Masalan, inisializatsiya qilinmagan o'zgaruvchi orqali ob'ektning maydonlariga murojaat qilaylik:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void main (){
Person? sam;
sam.age = 23;// Ошибка, sam = null
}
class Person{
String name = "undefined";
int age = 0;
void display(){
print("Name: $name Age: $age");
}
}
|
Sam.age = 23 qatori bajarilganda, dastur istisno qiladi va chiqadi. Chunki biz konstruktor yordamida Person sinfining obyektini yaratmadik. Shuning uchun, sam null, ya'ni aslida hech narsa yo'q, ob'ekt yo'q. Shunga ko'ra, biz mavjud bo'lmagan ob'ektning maydoniga murojaat qila olmaymiz. Xuddi shunday muammoga duch kelmaslik uchun biz boshqa operatordan foydalanishimiz mumkin -?. Maydonlarga murojaat qilish uchun.:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
void main (){
Person? sam;
sam?.age = 19;
sam?.display();
if(sam == null){
print("Переменная sam неопределена");
}
}
class Person{
String name = "undefined";
int age = 0;
void display(){
print("Name: $name Age: $age");
}
}
|
Operator?. o'zgaruvchining qiymatini tekshiring, agar o'zgaruvchi null bo'lmasa, u holda uning maydonlari va usullariga chaqiruv amalga oshiriladi. Agar u null bo'lsa, o'zgaruvchiga havola e'tiborga olinmaydi.
Nomlangan konstruktorlar
Odatiy bo'lib, biz faqat bitta umumiy konstruktorni belgilashimiz mumkin. Agar sinfda bir vaqtning o'zida bir nechta konstruktorlardan foydalanish kerak bo'lsa, bu holda biz nomli konstruktorlardan foydalanishimiz kerak. Masalan:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
void main (){
Person bob = Person.undefined(); // вызов первого конструктора без параметров
bob.display();
Person tom = Person.fromName("Tom"); // вызов второго конструктора с одним параметром
tom.display();
Person sam = Person("Sam", 25); // вызов третьего конструктора с двумя параметрами
sam.display();
}
class Person{
String name = "";
int age = 0;
Person.undefined(){
name = "undefined";
age = 18;
}
Person.fromName(String n){
name = n;
age = 18;
}
Person(String n, int a)
{
name = n;
age = a;
}
void display(){
print("Name: $name Age: $age");
}
}
|
Bu holda ikkita qo'shimcha konstruktor aniqlanadi: Person.undefined hech qanday parametrsiz va Person.fromName bitta parametrli. Bunday konstruktorlarni chaqirishda siz ularning to'liq ismini ko'rsatishingiz kerak: Shaxs tom = Person.fromName ("Tom");
Dasturning konsol chiqishi:
Name: undefined Age: 18
Name: Tom Age: 18
Name: Sam Age: 25
Bu kalit so'z
this kalit so'zi sinfning joriy nusxasiga havolani ifodalaydi. Ushbu kalit so'z orqali biz ob'ektning o'zgaruvchilari, usullariga murojaat qilishimiz, shuningdek uning konstruktorlarini chaqirishimiz mumkin. Masalan:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Person{
String name = "";
int age = 0;
Person(String name, int age)
{
this.name = name;
this.age = age;
}
void display(){
print("Name: $name Age: $age");
}
}
|
Konstruktorda parametrlar sinf maydonlari bilan bir xil nomlanadi. Maydonlar va parametrlarni farqlash uchun this kalit so'zi ishlatiladi:
Shunday qilib, bu holda biz nom parametrining qiymati nom maydoniga tayinlanganligini ko'rsatamiz.
Konstruktorning qisqartirilgan versiyasi
Bundan tashqari, this kalit so'zidan foydalanib, biz konstruktor ta'rifini qisqartirishimiz mumkin:
1
2
3
4
5
6
7
8
9
10
11
|
class Person{
String name;
int age;
Person(this.name, this.age);
void display(){
print("Name: $name Age: $age");
}
}
|
Konstruktor chaqirilganda:
1
|
Person sam = Person("Sam", 25);
|
Keyin "Sam" qatori this.name, 25 raqami esa - this.age uzatiladi.
Shuni ta'kidlash kerakki, konstruktorning ushbu ta'rifi bilan biz sinf maydonlari uchun boshlang'ich qiymatlarni o'rnatishimiz shart emas.
Konstruktor zanjirini chaqirish
Yuqoridagi konstruktor misolida bir xil ishni bajaradigan uchta konstruktor ishlatilgan: ular nom va yosh maydonlarini o'rnatdilar. Takrorlanishni oldini olish uchun, undan foydalanib, siz sinf konstruktorlaridan birini chaqirishingiz va uning parametrlari uchun kerakli qiymatlarni berishingiz mumkin. Natijada, biz turli xil miqdordagi parametrlarni qabul qiladigan va zanjir bo'ylab bir-birini chaqiradigan bir nechta konstruktorlarni aniqlay olamiz:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
void main (){
Person bob = Person.undefined(); // вызов первого конструктора без параметров
bob.display();
Person tom = Person.fromName("Tom"); // вызов второго конструктора с одним параметром
tom.display();
Person sam = Person("Sam", 25); // вызов третьего конструктора с двумя параметрами
sam.display();
}
class Person{
String name = "";
int age = 0;
Person.undefined(): this("undefined", 18);
Person.fromName(String name): this(name, 18);
Person(this.name, this.age);
void display(){
print("Name: $name Age: $age");
}
}
|
Bunday holda, birinchi va ikkinchi konstruktorlar uchinchisini chaqirishadi, unda nom va yosh maydonlari aslida o'rnatiladi.
Initializers
Initializers sinf maydonlarini ishga tushirish usulini taqdim etadi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
void main (){
Person tom = Person("Tom", 23);
tom.display();
}
class Person{
String name = "";
int age = 0;
Person(userName, userAge) : name=userName, age = userAge
{
print("Person ctor!");
}
void display(){
print("Name: $name Age: $age");
}
}
|
Initsializatsiya ro'yxati konstruktor parametrlaridan keyin ochiladigan jingalak qavs oldidan ikki nuqta bilan ajratilgan holda ko'rsatiladi:
1
|
Person(userName, userAge) : name=userName, age = userAge {
|
Odatda, ishga tushirish ro'yxatlari maydon qiymatlarini o'rnatish uchun konstruktor parametrlaridan foydalanadi. Bunday holda, konstruktor boshqa ishlarni bajarishi mumkin.
Shu bilan birga, maydonlarni ishga tushirishda siz qandaydir dinamik mantiqni o'rnatishingiz mumkin:
1
2
3
|
Person(userName, userAge) : name=userName, age = userAge + 10 {
print("Person ctor!");
}
|
Shuni yodda tutish kerakki, initsializatorlardan foydalanilganda, initsializatsiya ro'yxatlaridagi maydonlar birinchi navbatda ishga tushiriladi va shundan keyingina konstruktordagi mantiq bajariladi:
1
2
3
|
Person(userName, userAge) : name=userName, age = userAge + 10 {
age = 8;
}
|
Bunday holda, yosh maydonining qiymati 8 bo'ladi, chunki konstruktor initsializator tomonidan o'rnatilgan qiymatni qayta yozadi.
Kaskadli yozuv
Kaskadli yozuv - operatsiya .. bitta ob'ektda operatsiyalar ketma-ketligini bajarishga imkon beradi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
void main (){
Person tom = Person()
..name = "Tom"
..age = 36
..display(); // Name: Tom Age: 36
}
class Person{
String name = "";
int age = 0;
void display(){
print("Name: $name Age: $age");
}
}
|
Bunday holda, asosiy funktsiyadagi kod quyidagiga o'xshash bo'ladi:
1
2
3
4
5
6
7
|
void main (){
Person tom = Person();
tom.name = "Tom"
tom.age = 36
tom.display(); // Name: Tom Age: 36
}
|
Xuddi shunday, siz murakkabroq ob'ektlarga kirishingiz mumkin:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
void main (){
Person tom = Person()
..name = "Tom"
..age = 36
..company = (Company("Huawei")
..country = "Китай"
..payTaxes()
)
..display();
}
class Person{
String name = "";
int age = 0;
Company company = Company("");
void display(){
print("Имя: $name Возраст: $age");
print("работает в ${company.title}");
}
}
class Company{
String title = "";
String country = "";
Company(String companyTitle){
title = companyTitle;
}
payTaxes(){
print("Компания $title платит налоги \n");
}
}
|
Konsol chiqishi:
Компания Huawei платит налоги
Имя: Tom Возраст: 36
работает в Huawei
Agar konstruktorni chaqirishning hojati bo'lmasa, biz shunday yozishimiz mumkin edi:
1
2
3
4
5
6
7
8
9
10
|
void main (){
Person tom = Person()
..name = "Tom"
..age = 36
..company.title = "Huawei"
..company.country = "Китай"
..company.payTaxes()
..display();
}
|
|