10-bo‘lim
Vorislik va interfeyslar
Sinfdan meros olish, virtual va override, abstract sinflar, interfeyslar, polimorfizm hamda vorislik o'rniga kompozitsiya.
Ushbu bo‘lim mundarijasi
Vorislik - mavjud sinf asosida yangisini qurish. Interfeys esa "nima qila olishi" ni belgilaydigan shartnoma. Ikkalasi birgalikda polimorfizm ni beradi.
Oddiy vorislik #
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");
}
}
Men Husanboy, 25 yoshdaman
Informatika yo'nalishi talabasiman
Men Nodira, Matematika o'qituvchisiman
| Kalit so'z | Ma'nosi |
|---|---|
: Shaxs(...) | Shu sinfdan meros oladi |
virtual | Vorislar qayta yozishi mumkin |
override | Ota-ona metodini qayta yozadi |
base.Metod() | Ota-ona versiyasini chaqiradi |
virtual bo'lmasa qayta yozib bo'lmaydiC# 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:
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;
}
Doira maydoni = 78.54
To'rtburchak maydoni = 24.00
abstract a'zoning tanasi yo'q - voris uni albatta amalga
oshirishi shart. Kompilyator buni tekshiradi.
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:
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)}");
}
[konsol] Salom
[konsol] Dunyo
[xotira] 2 qator: Salom, Dunyo
I bilan boshlanadiBu 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:
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");
}
Hisobot saqlandi
Hisobot chop etildi
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? #
| Interfeys | Abstract sinf | |
|---|---|---|
| Nechtasini olish mumkin | Istalgancha | Bittasini |
| Maydon saqlay oladimi | Yo'q | Ha |
| Konstruktor | Yo'q | Ha |
| Tayyor kod | Cheklangan | Ha, 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 #
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;
}
Shakl, maydoni 12.57
Shakl, maydoni 9.00
Shakl emas: String
| Operator | Nima qiladi |
|---|---|
is Tur o'zgaruvchi | Tekshiradi va aylantiradi |
as Tur | Aylantiradi, bo'lmasa null |
(Tur)qiymat | Aylantiradi, bo'lmasa istisno |
sealed - vorislikni to'xtatish #
var x = new Yakuniy();
Console.WriteLine(x.Salom());
sealed class Yakuniy
{
public string Salom() => "Mendan meros olib bo'lmaydi";
}
Mendan meros olib bo'lmaydi
Vorislik o'rniga kompozitsiya #
Vorislik kuchli, lekin ko'pincha ortiqcha ishlatiladi.
Vorislik faqat "A - bu B ning turi" bo'lganda to'g'ri:
Talaba- buShaxsning turi. To'g'ri.Kvadrat- buShaklning turi. To'g'ri.Avtomobil- buDvigatelning turi? Yo'q. Avtomobilda dvigatel bor.
Ikkinchi holatda vorislik emas, kompozitsiya kerak - ya'ni obyektni maydon sifatida ichiga qo'yish:
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()}");
}
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.
ShaxssinfidanTalabavaOqituvchini meros oling.virtualmetodnioverrideqilib,baseni chaqiring.virtualni olib tashlab, kompilyator nima deyishini ko'ring.abstractShaklsinfi va uchta vorisini yozing.- Ularni bitta massivga solib, siklda maydonlarini chiqaring.
IYozuvchiinterfeysini ikki xil amalga oshiring.- Bitta sinfda ikkita interfeysni amalga oshiring.
isoperatori bilan turni tekshirib, xavfsiz aylantiring.sealedsinfdan meros olishga urinib ko'ring.AvtomobilvaDvigatelmisolida kompozitsiyani qo'llang.
Xulosa #
- Vorislik
: OtaSinfbilan e'lon qilinadi; C# da faqat bitta sinfdan meros olinadi. - Metodni qayta yozish uchun u
virtualbo'lishi va vorisoverrideyozishi shart. abstractsinfdan obyekt yaratib bo'lmaydi;abstracta'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
Ibilan 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.
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.