9-bo‘lim

Sinflar va obyektlar

Sinf e'lon qilish, maydon va xossalar, konstruktorlar, asosiy konstruktorlar, obyekt initsializatori, static a'zolar va kirish darajalari.

🕑 11 daqiqa o‘qish 📄 715 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Birinchi sinf
  2. Maydon va xossa
  3. Xossa turlari
  4. Asosiy konstruktor
  5. ToString ni qayta belgilash
  6. static a'zolar
  7. Kirish darajalari
  8. Obyekt initsializatori
  9. Xulosa

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 #

CSHARP
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}");
    }
}
Natija
Husanboy Qodirov, 25 yosh
Baholar soni: 3
O'rtacha: 90

Bu misolda sinfning barcha asosiy qismlari bor. Endi ularni birma-bir ko'rib chiqamiz.

Sinf pastda turibdi

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 #

CSHARP
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++;
    }
}
Natija
Malika: 80000 so'm
Amallar soni: 2
TushunchaNima
Maydon (field)Ma'lumot saqlanadigan joy, odatda private
Xossa (property)Maydonga nazorat ostida kirish
Avto-xossa{ get; set; } - maydonni kompilyator o'zi yaratadi
Maydonlarni doim private qiling

Bu 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 #

CSHARP
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;
}
Natija
Alpomish (1928) - Xalq dostoni
Yoshi: 98 yil
Yangilandi: Fozil Yo'ldosh o'g'li
YozuvMa'nosi
{ get; }Faqat konstruktorda o'rnatiladi
{ get; set; }Istalgan vaqtda o'zgartiriladi
{ get; init; }Faqat obyekt yaratilayotganda
=> ifodaHar 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:

CSHARP
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";
}
Natija
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:

CSHARP
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";
}
Natija
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:

CSHARP
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++;
    }
}
Natija
Yaratilgan foydalanuvchilar: 3
Oxirgisi: Nodira

Soni uchta obyekt uchun bitta. Unga obyekt orqali emas, sinf nomi orqali murojaat qilinadi: Foydalanuvchi.Soni.

static ni ehtiyotkorlik bilan ishlating

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.Sqrt kabi, 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 #

CSHARP
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}";
}
Natija
hamma ko'radi
faqat shu sinf ichida / shu sinf va vorislari / shu loyiha ichida
DarajaKimga ko'rinadi
publicHammaga
privateFaqat shu sinf ichida (sukut bo'yicha)
protectedShu sinf va undan meros olganlar
internalShu loyiha (assembly) ichida
Eng tor darajadan boshlang

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 #

CSHARP
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";
}
Natija
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.

Amaliy topshiriq
  1. Kitob sinfini yarating: nom, muallif, yil.
  2. Unga ToString() qo'shing va obyektni to'g'ridan-to'g'ri chiqaring.
  3. Maydonni private qilib, unga xossa orqali kirish bering.
  4. Xossaga tekshiruv qo'shing (masalan manfiy yil qabul qilmasin).
  5. { get; }, { get; set; } va { get; init; } farqini sinab ko'ring.
  6. Hisoblanadigan xossa yozing (masalan kitob yoshi).
  7. Asosiy konstruktor bilan qisqa sinf yarating.
  8. static hisoblagich bilan yaratilgan obyektlar sonini sanang.
  9. To'rtta kirish darajasini bitta sinfda sinab ko'ring.
  10. 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.
  • static sinfning o'ziga tegishli; dastur holatini unda saqlamang.
  • Kirish darajasini eng tordan boshlang.

Keyingi bo'limda vorislik va interfeyslarni o'rganamiz.

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.