CodeGym /Kurslar /C# SELF /Metodların override olunması (override) C#-da

Metodların override olunması (override) C#-da

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş

Təsəvvür elə ki, bizdə zooparkda heyvanların uçotu üçün bir tətbiq var (elə o nümunə ki, keçən dərslərdə başlatmışdıq). Biz Animal adlı əsas class yaratdıq və MakeSound metodunu əlavə etdik ki, bütün heyvanlar nəsə bir səs çıxara bilsin.


public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Heyvan səs çıxarır.");
    }
}
        
Virtual metodlu əsas class

Amma birdən məlum olur ki, şir və tutuquşunun səsləri tam fərqlidir. Universal "Heyvan səs çıxarır" artıq işə yaramır. Bax, burada metodların override olunması işə düşür. Sənə lazımdır ki, hər bir törəmə class özünəməxsus səslənsin!

2. Sintaksis: override necə işləyir

Əsas qaydalar

  • Metodu override etmək üçün o, əsas class-da virtual (və ya abstract) kimi işarələnməlidir.
  • Törəmə class-da metodun qarşısında override açar sözünü yazırıq və imzası eyni olmalıdır.

Nümunə: şirlər və tutuquşular

public class Lion : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Rrrrr!");
    }
}

public class Parrot : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Popka durak!");
    }
}

İndi əgər heyvanların siyahısını yaradıb hər birinə MakeSound çağırsaq, hərəsi öz səsini çıxaracaq:

Animal[] zoo = new Animal[]
{
    new Lion(),
    new Parrot(),
    new Animal()
};

foreach (var animal in zoo)
{
    animal.MakeSound();
}
// Çıxış:
// Rrrrr!
// Popka durak!
// Heyvan səs çıxarır.
Vacibdir: C# məhz obyektin real ( run-time) tipinə uyğun olan metodu çağıracaq, hətta dəyişənin tipi Animal olsa belə!

3. Virtual çağırış cədvəli (v-table)

Sən virtualoverride istifadə edəndə, compiler class üçün xüsusi "virtual metodlar cədvəli" (v-table) yaradır.
Metod əsas class referansı ilə çağırılanda CLR cədvələ baxır: görəsən bu metod törəmədə override olunub? Əgər bəli — törəmənin variantı çağırılır.
Bax, bu "gec bağlanma" (late binding) və ya dinamik polymorphism-in "sehridir".

4. Hamısını birləşdiririk: tətbiqimizi inkişaf etdiririk

Gəlin bir class da əlavə edək:

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Hav-hav!");
    }
}

Və bunu heyvanların uçotu üçün mini proqramımızda istifadə edək:

Animal[] zoo = new Animal[]
{
    new Lion(),
    new Parrot(),
    new Dog()
};

foreach (var animal in zoo)
{
    animal.MakeSound();
}

İndi kodun genişlənməsi və dəstəklənməsi qat-qat asan oldu, yeni heyvan əlavə etmək isə lap rahatdır!

5. Property-lərin override olunması və override ilə qaytarılan dəyər

Override etmək üçün təkcə metodlar deyil. Sən həmçinin virtual property və indexer-ləri də override edə bilərsən.

public class Animal
{
    public virtual string Name { get; set; } = "Heyvan";
}

public class Lion : Animal
{
    public override string Name { get; set; } = "Şir";
}

Bu xüsusilə, konkret növ üçün məlumatı dəqiqləşdirmək lazım olanda çox rahatdır.

6. base ilə əsas implementasiyanı çağırmaq

Bəzən əsas metodun davranışını tamamilə əvəz etmək yox, sadəcə genişləndirmək istəyirsən.
Bunun üçün override olunmuş metodun içində base açar sözü ilə əsas implementasiyanı çağırırıq.

public class Parrot : Animal
{
    public override void MakeSound()
    {
        base.MakeSound(); // "Heyvan səs çıxarır."
        Console.WriteLine("Popka durak!");
    }
}

Bu halda tutuquşu əvvəlcə ümumi "zoopark" səsini çıxaracaq, sonra isə öz məşhur "Popka durak!" deyəcək.

7. Praktik fayda: harada istifadə olunur

override mexanizmini başa düşmək demək olar ki, hər ciddi C# layihəsində, OOP aktiv istifadə olunanda lazımdır.

  • Zooparkdakı heyvan modelləri? Artıq etmişik.
  • UI üçün custom control-lar yaratmaq: Standart vizual metodları override edib öz məntiqini əlavə edirsən.
  • Elastik biznes-məntiq: Əsas class-larda "skelet" davranış qurursan, detalları isə törəmələrdə reallaşdırırsan.
  • Test və mock-lar: Unit-test üçün metodları asanlıqla törəmələr vasitəsilə "əvəzləmək" olur.
  • Plugin və genişlənmələr: Interface və ya abstract əsas class, bir neçə implementasiya — və hər şey düzgün override sayəsində işləyir.

8. sealed override və virtual metodlar zəncirdə

Əgər istəmirsənsə ki, sənin override etdiyin metod daha aşağıda yenidən override olunsun, sealed override istifadə edə bilərsən:

public class Base
{
    public virtual void Foo() { }
}

public class Middle : Base
{
    public sealed override void Foo() { }
}

public class Last : Middle
{
    public override void Foo() {} // Səhv — override etmək olmaz!
}

Bu, override zəncirini məhz sistemin düzgün işləməsi üçün vacib olan yerdə "bağlamağa" imkan verir.

9. Yeni metod ( new açar sözü )

Bəzən istəyirsən ki, törəmədə eyni imzalı metod elan edəsən, amma əsas class-da metod virtual deyil.
Belə halda new açar sözündən istifadə etmək olar — amma bu polymorphism deyil, sadəcə "maskalama"dır:

public class Animal
{
    public void MakeSound()
    {
        Console.WriteLine("Mən heyvanam!");
    }
}

public class Cat : Animal
{
    public new void MakeSound()
    {
        Console.WriteLine("Mən pişikəm!");
    }
}

Animal animal = new Cat();
animal.MakeSound(); // "Mən heyvanam!"
Cat cat = new Cat();
cat.MakeSound(); // "Mən pişikəm!"

Burada hər şeyi çağırış zamanı dəyişənin tipi həll edir! Ona görə də həqiqi dinamik polymorphism üçün həmişə virtual + override kombinasiyasından istifadə et.

10. Metodları override edəndə tipik səhvlər

Səhv №1: virtual, abstract və ya override kimi işarələnməmiş metodu override etməyə cəhd.
C#-da adi metodları override etmək olmur. Əgər əsas class-da metod xüsusi modifier-lə (virtual, abstract və ya override) işarələnməyibsə, törəmədə override yazmaq compiler səhvinə səbəb olacaq.

Səhv №2: metodun imzası uyğun gəlmir.
Metodun həqiqətən override olunması üçün adı, qaytardığı tip və parametrləri əsas class-dakı ilə tam uyğun olmalıdır. Kiçik bir fərq (məsələn, başqa parametr tipi) yeni metod yaradacaq, override yox.

Səhv №3: override modifier-i unutmaq.
Əgər sən əsas class-dakı ilə eyni imzalı metod yazmısan, amma override göstərməmisən, compiler bunu override saymır. Bu, metodun gizlədilməsi adlanır (ayrıca baxılacaq). Belə halda əsas tipli dəyişənlə metod çağıranda gözlənilməz nəticə alırsan — əsas metod çağırılır, sənin yox.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION