1. Giriş
Təsəvvür elə, səndə Animal adlı əsas class var və orda Speak() metodu var. Bütün heyvanlar üçün default olaraq o yazır "Hər hansı bir səs". İstəyirsən ki, miras alan class-lar, məsələn, Dog və Cat öz səslərini çıxarsınlar, yəni "Hər hansı bir səs" yox, öz real frazalarını ("Hav-hav!" və "Miyav!") desinlər.
Hər miras alan class-da öz Speak() metodunu yaza bilərdin, amma əgər sən Animal[] tipli kolleksiya ilə işləyirsənsə, animal.Speak() çağırışı yenə də Animal metoduna müraciət edəcək, itə və ya pişiyə yox — çünki C# default olaraq dəyişənin tipinə baxır, arxasında duran real obyektə yox.
Barmaqla izah olunan nümunə:
Animal dog = new Dog();
dog.Speak(); // Baxaq, nə çıxacaq?
Default olaraq — "Hər hansı bir səs", "Hav-hav!" yox, hətta Dog-da öz Speak() metodu olsa belə. Bəs nə etməli? Metodu virtual (əsas class-da) və override (miras alan class-da) kimi elan etmək lazımdır.
Virtual metod nədir?
virtual-metod — əsas class-da virtual modifikatoru ilə elan olunan və miras alanlarda override etmək üçün nəzərdə tutulan metoddur ( override).Belə metodu əsas class-a istinadla çağıranda, real obyektin öz metodu çağırılır — həyatda olduğu kimi: əgər sən heyvanı evcilləşdirmisənsə və o pişikdirsə, o "Miyav!" deyəcək, "Hər hansı bir səs" yox.
Virtual metodlar — C#-da polimorfizmin əsasını təşkil edir.
2. Virtual metodların elan olunması
Virtual metodu necə elan etmək olar
Əsas class-da metodu virtual açar sözü ilə elan edirik:
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("Hər hansı bir səs");
}
}
Miras alan class-da override açar sözündən istifadə edirik:
public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Hav-hav!");
}
}
public class Cat : Animal
{
public override void Speak()
{
Console.WriteLine("Miyav!");
}
}
Nümunə: polimorfizmin nümayişi
// Məsələn, Program.cs faylında
// Əsas class Animal, virtual Speak metodu ilə
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("Hər hansı bir səs");
}
}
// Dog class-ı, Speak davranışını override edir
public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Hav-hav!");
}
}
// Cat class-ı da Speak-i override edir
public class Cat : Animal
{
public override void Speak()
{
Console.WriteLine("Miyav!");
}
}
public static class Program
{
public static void Main()
{
Animal[] animals = new Animal[]
{
new Animal(),
new Dog(),
new Cat()
};
foreach (Animal animal in animals)
{
animal.Speak(); // Çıxacaq: "Hər hansı bir səs", "Hav-hav!", "Miyav!"
}
}
}
Gördün, virtual metod necə magiya edir? Dəyişənin tipi Animal olsa belə, metodun ən konkret implementasiyası çağırılır.
3. "Qapağın altında" nə baş verir: virtual cədvəl
Mexanizm qısa izah
Metodu virtual kimi elan edəndə, compiler hər tip üçün xüsusi "virtual cədvəl"ə onu əlavə edir (demək olar ki, hər yeməyə ayrıca menyu kimi). Belə metod çağırılanda, C# dəyişənin tipinə yox, istinadda real nə var ona baxır — və real obyektin tipinə uyğun metodu "gətirir".
Yəni, C# lazım olan resepti universalın yerinə qoyur, əgər class-da öz variantı varsa.
Bənzətmə: "kiçik şriftlə əlavə bənd yazmaq imkanı olan müqavilə"
Təsəvvür elə, səndə icarə müqaviləsi var (əsas class), və orda yazılıb ki, icarəçi default olaraq hər ay sabit məbləğ ödəyir (PayRent() metodu). Amma sən — hiyləgər sahib — müqaviləyə əlavələrdə xüsusi şərtlər yazmağa icazə verirsən (virtual metod). Əgər icarəçilərdən biri (miras alan) bu hüquqdan istifadə etsə, öz override-unu yazacaq və artıq ödəniş xüsusi qaydada olacaq.
4. Virtual metodlardan nə vaxt istifadə etməli?
- Əgər əsas class-da metod əksər miras alanlar üçün tipik işləməlidirsə, amma bəziləri fərqli davranış tələb edə bilərsə.
- Class-lar iyerarxiyası quranda, hansısa logikanı genişləndirmək və ya dəyişmək ehtimalı varsa.
- Çevik arxitektura quranda, məsələn, biznes-logika üçün, müxtəlif əməliyyat tipləri fərdi davranış tələb edə bilər.
Real layihələrdə virtual metodlar — Template Method (Şablon metod), Strategy (Strategiya) kimi pattern-lərin və ümumiyyətlə OOP-nin yarısının əsasını təşkil edir.
Adi metodlarla müqayisə
| Adi metod | Virtual metod | |
|---|---|---|
| Override etmək olar | Yox | Bəli (override) |
| Necə çağırılır | Dəyişənin tipinə görə | "Real" obyektin tipinə görə |
| Polimorfizm | Yox | Bəli |
Tez-tez verilən suallar
- Konstruktoru virtual etmək olar?
Yox! Konstruktorlar heç vaxt virtual olmur — onlar həmişə obyektin tipinə görə işləyir. - Virtual metodlar static ola bilər?
Yox, yalnız instance metodlar virtual ola bilər. Static metodlar polimorfizmdə iştirak etmir, çünki obyekt yoxdur — bəs kim override edəcək? - Field-lər virtual ola bilər?
Yox, yalnız metodlar, property-lər və event-lər.
5. Praktika: "Heyvanlar aləmi" tətbiqini inkişaf etdiririk
Tədris tətbiqimizdə artıq sadə heyvan iyerarxiyası yaratmısan. Gəlin heyvanlara yeni virtual metodlar əlavə edək ki, müxtəlif heyvanlar fərqli şəkildə yesinlər!
Şərhlərlə kod nümunəsi
// Əsas class-da virtual Eat metodu veririk
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("Hər hansı bir səs");
}
public virtual void Eat()
{
Console.WriteLine("Adi yemək yeyir.");
}
}
// Dog-da Eat-ı override edirik
public class Dog : Animal
{
public override void Speak() => Console.WriteLine("Hav-hav!");
public override void Eat() => Console.WriteLine("İt yeməyi yeyir.");
}
// Cat-da da öz davranışı var
public class Cat : Animal
{
public override void Speak() => Console.WriteLine("Miyav!");
public override void Eat() => Console.WriteLine("Balıq yeyir.");
}
public static class Program
{
public static void Main()
{
Animal[] animals = new Animal[]
{
new Animal(),
new Dog(),
new Cat()
};
foreach (var animal in animals)
{
animal.Speak();
animal.Eat();
Console.WriteLine("---");
}
}
}
Bax belə, indi hər pişik və it öz yeməyini yeyir! Əsas Animal isə hələ də nəsə qəribə bir şey yeyir, tam "default" kimi.
6. Tipik səhvlər və nüanslar
- Miras alan class-da override yazmağı unuda bilərsən — onda əsas class-ın metodu yerində qalacaq.
- Və ya əksinə, əsas class-da virtual yazmağı unutsan, miras alan class-da override yaza bilməyəcəksən.
override yazmaq olmaz əgər virtual yoxdursa
C# compiler-i virtual (və ya abstract) elan olunmayan metodu override etməyə icazə vermir.
override nə üçün lazımdır
override compiler-ə və kodu oxuyana açıq şəkildə deyir: "Mən sadəcə yeni metod yazmıram — əsas class-da veriləni bilərəkdən dəyişirəm". Bu, səhvlərin qarşısını alır, çünki bəzən "override" etmək istəyirsən, amma təsadüfən sadəcə oxşar imzalı yeni metod yazırsan.
override yazmağı unudub yeni metod yazsan
public class Dog : Animal
{
public void Speak()
{
Console.WriteLine("Hav-hav!");
}
}
Amma bu override deyil! Dog-a Animal tipli dəyişənlə müraciət edəndə, heyvanın metodu ("Hər hansı bir səs") çağırılacaq, itin yox. Bax belə, tiplərlə gözlənilməz görüş!
GO TO FULL VERSION