10-bo‘lim

Vorislik va interfeyslar

Sinfdan meros olish, virtual va override, abstract sinflar, interfeyslar, polimorfizm hamda vorislik o'rniga kompozitsiya.

🕑 11 daqiqa o‘qish 📄 719 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Oddiy vorislik
  2. abstract - to'liqsiz sinf
  3. Interfeys
  4. Bir nechta interfeys
  5. Interfeys yoki abstract sinf?
  6. Turni tekshirish
  7. sealed - vorislikni to'xtatish
  8. Vorislik o'rniga kompozitsiya
  9. Xulosa

Vorislik - mavjud sinf asosida yangisini qurish. Interfeys esa "nima qila olishi" ni belgilaydigan shartnoma. Ikkalasi birgalikda polimorfizm ni beradi.

Oddiy vorislik #

CSHARP
var t = new Talaba("Husanboy", 25, "Informatika");
var o = new Oqituvchi("Nodira", 40, "Matematika");

t.Tanishtir();
o.Tanishtir();

class Shaxs(string ism, int yosh)
{
    public string Ism => ism;
    public int Yosh => yosh;

    public virtual void Tanishtir()
    {
        Console.WriteLine($"Men {Ism}, {Yosh} yoshdaman");
    }
}

class Talaba(string ism, int yosh, string yonalish) : Shaxs(ism, yosh)
{
    public string Yonalish => yonalish;

    public override void Tanishtir()
    {
        base.Tanishtir();
        Console.WriteLine($"  {Yonalish} yo'nalishi talabasiman");
    }
}

class Oqituvchi(string ism, int yosh, string fan) : Shaxs(ism, yosh)
{
    public override void Tanishtir()
    {
        Console.WriteLine($"Men {Ism}, {fan} o'qituvchisiman");
    }
}
Natija
Men Husanboy, 25 yoshdaman
  Informatika yo'nalishi talabasiman
Men Nodira, Matematika o'qituvchisiman
Kalit so'zMa'nosi
: Shaxs(...)Shu sinfdan meros oladi
virtualVorislar qayta yozishi mumkin
overrideOta-ona metodini qayta yozadi
base.Metod()Ota-ona versiyasini chaqiradi
virtual bo'lmasa qayta yozib bo'lmaydi

C# da metodlar sukut bo'yicha qayta yozilmaydi. Vorisga ruxsat berish uchun virtual deb belgilash kerak.

Bu Java'dan farqi: u yerda hamma metod sukut bo'yicha virtual.

C# ning yondashuvi ataylab tanlangan: metodni virtual qilish - bu va'da. Siz vorislar uni o'zgartirishini rejalashtirgan bo'lishingiz kerak, tasodifan emas.

abstract - to'liqsiz sinf #

abstract sinfdan obyekt yaratib bo'lmaydi; u faqat asos bo'lib xizmat qiladi:

CSHARP
Shakl[] shakllar =
[
    new Doira(5),
    new Togritortburchak(4, 6)
];

foreach (Shakl shakl in shakllar)
{
    Console.WriteLine($"{shakl.Nomi,-16} maydoni = {shakl.Maydon():F2}");
}

abstract class Shakl
{
    public abstract string Nomi { get; }
    public abstract double Maydon();
}

class Doira(double radius) : Shakl
{
    public override string Nomi => "Doira";
    public override double Maydon() => Math.PI * radius * radius;
}

class Togritortburchak(double eni, double boyi) : Shakl
{
    public override string Nomi => "To'rtburchak";
    public override double Maydon() => eni * boyi;
}
Natija
Doira            maydoni = 78.54
To'rtburchak     maydoni = 24.00

abstract a'zoning tanasi yo'q - voris uni albatta amalga oshirishi shart. Kompilyator buni tekshiradi.

Bu polimorfizm

Diqqat qiling: sikl Shakl turi bilan ishlaydi va har bir element uchun o'zining Maydon() metodi chaqirildi.

Kod qaysi aniq shakl kelishini bilmaydi, lekin to'g'ri ishlaydi. Yangi shakl qo'shsangiz - masalan uchburchak - bu siklni umuman o'zgartirish kerak emas.

Aynan shu polimorfizm deb ataladi va obyektga yo'naltirilgan dasturlashning asosiy foydasi shu.

Interfeys #

Interfeys - faqat nima qila olishini aytadi, qanday qilishini emas:

CSHARP
IYozuvchi[] chiqishlar = [new Konsolga(), new Xotiraga()];

foreach (IYozuvchi yozuvchi in chiqishlar)
{
    yozuvchi.Yoz("Salom");
    yozuvchi.Yoz("Dunyo");
}

(chiqishlar[1] as Xotiraga)?.Korsat();

interface IYozuvchi
{
    void Yoz(string matn);
}

class Konsolga : IYozuvchi
{
    public void Yoz(string matn) => Console.WriteLine($"[konsol] {matn}");
}

class Xotiraga : IYozuvchi
{
    private readonly List<string> qatorlar = [];

    public void Yoz(string matn) => qatorlar.Add(matn);

    public void Korsat() => Console.WriteLine(
        $"[xotira] {qatorlar.Count} qator: {string.Join(", ", qatorlar)}");
}
Natija
[konsol] Salom
[konsol] Dunyo
[xotira] 2 qator: Salom, Dunyo
Interfeys nomi I bilan boshlanadi

Bu C# da qat'iy qabul qilingan an'ana: IYozuvchi, IDisposable, IEnumerable.

Kod o'qiyotganda I harfi darhol "bu interfeys" deb bildiradi - tur e'loniga qarash shart emas.

Bir nechta interfeys #

Sinf bitta sinfdan meros oladi, lekin istalgancha interfeysni amalga oshirishi mumkin:

CSHARP
var h = new Hujjat("Hisobot");
h.Saqla();
h.Chop();

interface ISaqlanadigan
{
    void Saqla();
}

interface IChopEtiladigan
{
    void Chop();
}

class Hujjat(string nom) : ISaqlanadigan, IChopEtiladigan
{
    public void Saqla() => Console.WriteLine($"{nom} saqlandi");
    public void Chop() => Console.WriteLine($"{nom} chop etildi");
}
Natija
Hisobot saqlandi
Hisobot chop etildi
Nega faqat bitta sinfdan meros?

Bir nechta sinfdan meros olish "olmos muammosi" ni keltirib chiqaradi: ikkita ota-onada bir xil nomli metod bo'lsa, qaysi biri ishlashi noaniq bo'lib qoladi.

C++ da bu mumkin va shu sababli murakkab qoidalar kerak. C# va Java bu yo'ldan bormaslikka qaror qilgan: bitta sinf, istalgancha interfeys.

Interfeyslarda bunday muammo yo'q, chunki ularda odatda tana bo'lmaydi.

Interfeys yoki abstract sinf? #

InterfeysAbstract sinf
Nechtasini olish mumkinIstalganchaBittasini
Maydon saqlay oladimiYo'qHa
KonstruktorYo'qHa
Tayyor kodCheklanganHa, to'liq
Qachon"Nima qila oladi""Nima ekanligi"

Qoida: "bu shunday qila oladi" desangiz - interfeys (IYozuvchi). "bu shunday narsa" desangiz - abstract sinf (Shakl).

Turni tekshirish #

CSHARP
object[] narsalar = [new Doira(2), new Kvadrat(3), "matn"];

foreach (object narsa in narsalar)
{
    if (narsa is Shakl shakl)
    {
        Console.WriteLine($"Shakl, maydoni {shakl.Maydon():F2}");
    }
    else
    {
        Console.WriteLine($"Shakl emas: {narsa.GetType().Name}");
    }
}

abstract class Shakl
{
    public abstract double Maydon();
}

class Doira(double r) : Shakl
{
    public override double Maydon() => Math.PI * r * r;
}

class Kvadrat(double t) : Shakl
{
    public override double Maydon() => t * t;
}
Natija
Shakl, maydoni 12.57
Shakl, maydoni 9.00
Shakl emas: String
OperatorNima qiladi
is Tur o'zgaruvchiTekshiradi va aylantiradi
as TurAylantiradi, bo'lmasa null
(Tur)qiymatAylantiradi, bo'lmasa istisno

sealed - vorislikni to'xtatish #

CSHARP
var x = new Yakuniy();
Console.WriteLine(x.Salom());

sealed class Yakuniy
{
    public string Salom() => "Mendan meros olib bo'lmaydi";
}
Natija
Mendan meros olib bo'lmaydi

Vorislik o'rniga kompozitsiya #

Vorislik kuchli, lekin ko'pincha ortiqcha ishlatiladi.

"Meros" munosabatni to'g'ri tekshiring

Vorislik faqat "A - bu B ning turi" bo'lganda to'g'ri:

  • Talaba - bu Shaxs ning turi. To'g'ri.
  • Kvadrat - bu Shakl ning turi. To'g'ri.
  • Avtomobil - bu Dvigatel ning turi? Yo'q. Avtomobilda dvigatel bor.

Ikkinchi holatda vorislik emas, kompozitsiya kerak - ya'ni obyektni maydon sifatida ichiga qo'yish:

CSHARP
var mashina = new Avtomobil("Nexia");
mashina.Yur();

class Dvigatel
{
    public string Ishga() => "dvigatel ishga tushdi";
}

class Avtomobil(string nom)
{
    private readonly Dvigatel dvigatel = new();

    public void Yur() => Console.WriteLine($"{nom}: {dvigatel.Ishga()}");
}
Natija
Nexia: dvigatel ishga tushdi

Bu moslashuvchanroq: dvigatelni keyin boshqasiga almashtirish mumkin, Avtomobil esa o'zgarmaydi.

Amaliy qoida: avval kompozitsiyani o'ylang, vorislikni faqat haqiqatan "bu shuning turi" bo'lganda ishlating.

Amaliy topshiriq
  1. Shaxs sinfidan Talaba va Oqituvchi ni meros oling.
  2. virtual metodni override qilib, base ni chaqiring.
  3. virtual ni olib tashlab, kompilyator nima deyishini ko'ring.
  4. abstract Shakl sinfi va uchta vorisini yozing.
  5. Ularni bitta massivga solib, siklda maydonlarini chiqaring.
  6. IYozuvchi interfeysini ikki xil amalga oshiring.
  7. Bitta sinfda ikkita interfeysni amalga oshiring.
  8. is operatori bilan turni tekshirib, xavfsiz aylantiring.
  9. sealed sinfdan meros olishga urinib ko'ring.
  10. Avtomobil va Dvigatel misolida kompozitsiyani qo'llang.

Xulosa #

  • Vorislik : OtaSinf bilan e'lon qilinadi; C# da faqat bitta sinfdan meros olinadi.
  • Metodni qayta yozish uchun u virtual bo'lishi va voris override yozishi shart.
  • abstract sinfdan obyekt yaratib bo'lmaydi; abstract a'zoni voris majburan amalga oshiradi.
  • Polimorfizm - asosiy tur bilan ishlab, har bir obyektning o'z xatti-harakatini olish.
  • Interfeys - "nima qila oladi"; abstract sinf - "nima ekanligi".
  • Interfeys nomi I bilan boshlanadi; ularni istalgancha olish mumkin.
  • is Tur o'zgaruvchi - tekshirish va aylantirishning eng xavfsiz usuli.
  • Munosabat "bu shuning turi" bo'lmasa - vorislik emas, kompozitsiya.

Keyingi bo'limda struct va record turlarini ko'ramiz.

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.