9-bo‘lim
Sinflar va obyektlar
Sinf e'lon qilish, maydon va xossalar, konstruktorlar, asosiy konstruktorlar, obyekt initsializatori, static a'zolar va kirish darajalari.
Ushbu bo‘lim mundarijasi
Sinf - o'zingiz yaratadigan tur. U ma'lumot (maydonlar) va shu ma'lumot ustidagi amallarni (metodlar) bir joyga jamlaydi.
Shu paytgacha tayyor turlardan foydalandik. Endi o'zimiznikini yaratamiz.
Birinchi sinf #
var talaba = new Talaba("Husanboy Qodirov", 25);
talaba.BallQoshish(90);
talaba.BallQoshish(85);
talaba.BallQoshish(95);
talaba.Korsat();
class Talaba
{
private readonly List<int> ballar = [];
public string Ism { get; }
public int Yosh { get; }
public Talaba(string ism, int yosh)
{
Ism = ism;
Yosh = yosh;
}
public void BallQoshish(int ball) => ballar.Add(ball);
public double Ortacha => ballar.Count == 0 ? 0 : ballar.Average();
public void Korsat()
{
Console.WriteLine($"{Ism}, {Yosh} yosh");
Console.WriteLine($"Baholar soni: {ballar.Count}");
Console.WriteLine($"O'rtacha: {Ortacha}");
}
}
Husanboy Qodirov, 25 yosh
Baholar soni: 3
O'rtacha: 90
Bu misolda sinfning barcha asosiy qismlari bor. Endi ularni birma-bir ko'rib chiqamiz.
Yuqori darajali ko'rsatmalarda avval kod, keyin turlar yoziladi. Sinfni yuqoriga ko'chirsangiz, kompilyator xato beradi.
Haqiqiy loyihada har bir sinf o'z faylida turadi: Talaba.cs,
Mijoz.cs. Bu darslikda ular bitta faylda, chunki misol qisqa
bo'lishi kerak.
Maydon va xossa #
var hisob = new Hisob();
hisob.Egasi = "Malika";
hisob.Qoshish(50000);
hisob.Qoshish(30000);
Console.WriteLine($"{hisob.Egasi}: {hisob.Balans} so'm");
Console.WriteLine($"Amallar soni: {hisob.AmallarSoni}");
class Hisob
{
private decimal balans; // maydon - tashqaridan ko'rinmaydi
private int amallar;
public string Egasi { get; set; } = ""; // avto-xossa
public decimal Balans => balans; // faqat o'qish
public int AmallarSoni => amallar;
public void Qoshish(decimal miqdor)
{
if (miqdor <= 0)
{
throw new ArgumentException("Miqdor musbat bo'lishi kerak");
}
balans += miqdor;
amallar++;
}
}
Malika: 80000 so'm
Amallar soni: 2
| Tushuncha | Nima |
|---|---|
| Maydon (field) | Ma'lumot saqlanadigan joy, odatda private |
| Xossa (property) | Maydonga nazorat ostida kirish |
| Avto-xossa | { get; set; } - maydonni kompilyator o'zi yaratadi |
private qilingBu obyektga yo'naltirilgan dasturlashning asosiy qoidasi - inkapsulyatsiya.
Yuqoridagi misolda balans ni tashqaridan o'zgartirib bo'lmaydi. Uni
faqat Qoshish metodi orqali o'zgartirish mumkin va u tekshiruv
o'tkazadi.
Agar balans ochiq bo'lganida, istalgan kod uni manfiy qilib
qo'yishi mumkin edi va buni kim qilganini topish deyarli imkonsiz
bo'lardi.
Xossa turlari #
var kitob = new Kitob("Alpomish") { Muallif = "Xalq dostoni", Yili = 1928 };
Console.WriteLine($"{kitob.Nom} ({kitob.Yili}) - {kitob.Muallif}");
Console.WriteLine($"Yoshi: {kitob.Yoshi} yil");
kitob.Muallif = "Fozil Yo'ldosh o'g'li";
Console.WriteLine($"Yangilandi: {kitob.Muallif}");
class Kitob
{
public string Nom { get; } // faqat konstruktorda
public string Muallif { get; set; } = ""; // o'qish va yozish
public int Yili { get; init; } // faqat yaratishda
public int Yoshi => 2026 - Yili; // hisoblanadigan
public Kitob(string nom) => Nom = nom;
}
Alpomish (1928) - Xalq dostoni
Yoshi: 98 yil
Yangilandi: Fozil Yo'ldosh o'g'li
| Yozuv | Ma'nosi |
|---|---|
{ get; } | Faqat konstruktorda o'rnatiladi |
{ get; set; } | Istalgan vaqtda o'zgartiriladi |
{ get; init; } | Faqat obyekt yaratilayotganda |
=> ifoda | Har safar qaytadan hisoblanadi |
init nima uchun kerak{ get; set; } obyektni istalgan payt o'zgartirishga ruxsat beradi.
{ get; } esa faqat konstruktordan o'rnatadi - obyekt initsializatori
bilan ishlamaydi.
init ikkalasining o'rtasi: obyekt yaratilayotganda o'rnatish
mumkin, keyin esa yo'q.
Yuqoridagi misolda Yili ni { Yili = 1928 } ko'rinishida berdik,
lekin keyin kitob.Yili = 2000 deb yozib bo'lmaydi - kompilyator
ruxsat bermaydi.
Asosiy konstruktor #
C# 12 dan sinf nomining yonida parametr yozish mumkin:
var m1 = new Mahsulot("Non", 4000);
var m2 = new Mahsulot("Sut", 12000);
Console.WriteLine(m1);
Console.WriteLine(m2);
Console.WriteLine($"Jami: {m1.Narx + m2.Narx} so'm");
class Mahsulot(string nom, decimal narx)
{
public string Nom => nom;
public decimal Narx => narx;
public override string ToString() => $"{nom} - {narx} so'm";
}
Non - 4000 so'm
Sut - 12000 so'm
Jami: 16000 so'm
Konstruktor yozish shart bo'lmadi - parametrlar to'g'ridan-to'g'ri sinf ichida ishlatiladi. Bu qisqa sinflar uchun juda qulay.
ToString ni qayta belgilash #
Yuqorida ToString() ni qayta yozdik. Usiz nima bo'lishini ko'ramiz:
var a = new Oddiy();
var b = new Chiroyli();
Console.WriteLine(a);
Console.WriteLine(b);
class Oddiy { }
class Chiroyli
{
public override string ToString() => "Men o'zimni tanishtira olaman";
}
Oddiy
Men o'zimni tanishtira olaman
Sukut bo'yicha ToString() shunchaki tur nomini qaytaradi. Bu
nosozliklarni qidirishda foydasiz, shuning uchun o'z sinflaringizda uni
qayta belgilash yaxshi odat.
static a'zolar #
static - sinfning o'ziga tegishli, har bir obyektga emas:
var a = new Foydalanuvchi("Husanboy");
var b = new Foydalanuvchi("Malika");
var c = new Foydalanuvchi("Nodira");
Console.WriteLine($"Yaratilgan foydalanuvchilar: {Foydalanuvchi.Soni}");
Console.WriteLine($"Oxirgisi: {c.Ism}");
class Foydalanuvchi
{
public static int Soni { get; private set; }
public string Ism { get; }
public Foydalanuvchi(string ism)
{
Ism = ism;
Soni++;
}
}
Yaratilgan foydalanuvchilar: 3
Oxirgisi: Nodira
Soni uchta obyekt uchun bitta. Unga obyekt orqali emas, sinf
nomi orqali murojaat qilinadi: Foydalanuvchi.Soni.
static holat butun dastur bo'ylab bitta bo'ladi va uni kim
o'zgartirganini kuzatish qiyin.
U quyidagilar uchun to'g'ri keladi:
- Yordamchi metodlar -
Math.Sqrtkabi, holatsiz; - Doimiylar -
Math.PI; - Hisoblagichlar - yuqoridagi misol kabi.
Lekin dastur holatini static maydonlarda saqlash - keyinchalik
tuzatish juda qiyin bo'ladigan kod yaratadi. Ayniqsa bir nechta oqim
bilan ishlaganda (18-bo'lim).
Kirish darajalari #
var q = new Qutti();
Console.WriteLine(q.Ochiq);
Console.WriteLine(q.Korsat());
class Qutti
{
public string Ochiq = "hamma ko'radi";
private string yopiq = "faqat shu sinf ichida";
protected string himoyalangan = "shu sinf va vorislari";
internal string ichki = "shu loyiha ichida";
public string Korsat() => $"{yopiq} / {himoyalangan} / {ichki}";
}
hamma ko'radi
faqat shu sinf ichida / shu sinf va vorislari / shu loyiha ichida
| Daraja | Kimga ko'rinadi |
|---|---|
public | Hammaga |
private | Faqat shu sinf ichida (sukut bo'yicha) |
protected | Shu sinf va undan meros olganlar |
internal | Shu loyiha (assembly) ichida |
Yangi a'zo qo'shayotganda uni private qilib boshlang. Keyin
haqiqatan tashqaridan kerak bo'lsa, kengaytirasiz.
Teskarisi qiyin: public qilingan narsani keyin yopish - undan
foydalanayotgan barcha kodni buzadi.
Obyekt initsializatori #
var m = new Manzil
{
Viloyat = "Namangan",
Tuman = "Chust",
Kocha = "Navoiy",
Uy = 14
};
Console.WriteLine(m);
class Manzil
{
public string Viloyat { get; init; } = "";
public string Tuman { get; init; } = "";
public string Kocha { get; init; } = "";
public int Uy { get; init; }
public override string ToString() =>
$"{Viloyat} viloyati, {Tuman} tumani, {Kocha} ko'chasi, {Uy}-uy";
}
Namangan viloyati, Chust tumani, Navoiy ko'chasi, 14-uy
Ko'p parametrli konstruktor yozish o'rniga, xossalarni nom bilan o'rnatish mumkin - kod ancha tushunarli bo'ladi.
Kitobsinfini yarating: nom, muallif, yil.- Unga
ToString()qo'shing va obyektni to'g'ridan-to'g'ri chiqaring. - Maydonni
privateqilib, unga xossa orqali kirish bering. - Xossaga tekshiruv qo'shing (masalan manfiy yil qabul qilmasin).
{ get; },{ get; set; }va{ get; init; }farqini sinab ko'ring.- Hisoblanadigan xossa yozing (masalan kitob yoshi).
- Asosiy konstruktor bilan qisqa sinf yarating.
statichisoblagich bilan yaratilgan obyektlar sonini sanang.- To'rtta kirish darajasini bitta sinfda sinab ko'ring.
- Obyekt initsializatori bilan obyekt yarating.
Xulosa #
- Sinf - o'zingiz yaratadigan tur: ma'lumot va amallar birgalikda.
- Yuqori darajali ko'rsatmalarda sinflar kod pastida e'lon qilinadi.
- Maydonlar
private, tashqariga xossa orqali chiqariladi - bu inkapsulyatsiya. { get; }konstruktorda,{ get; init; }yaratishda,{ get; set; }istalgan vaqtda o'rnatiladi.- Asosiy konstruktor (
class Mahsulot(string nom)) qisqa sinflar uchun qulay. ToString()ni qayta belgilang - sukut qiymati foydasiz.staticsinfning o'ziga tegishli; dastur holatini unda saqlamang.- Kirish darajasini eng tordan boshlang.
Keyingi bo'limda vorislik va interfeyslarni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.