CodeGym /Kurslar /C# SELF /Metodların yenidən təyin edilməsi (Method Overriding) C#-...

Metodların yenidən təyin edilməsi (Method Overriding) C#-da

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

1. Giriş

Əgər indi yenidən təyin etmə sözündən bir az tərləmisənsə, narahat olma — bu qorxulu deyil, əksinə çox rahatdır! Metodun yenidən təyin edilməsi — bu, əsas class-dakı metodun davranışını törəmə class-da özününkü ilə əvəzləmək imkanıdır. Bunun sayəsində kodumuz çevik, genişlənə bilən və real həyata hazır olur, axı hər bir heyvan sadəcə "nə isə bir səs" olmaq istəmir.

Metodun yenidən təyin edilməsinə icazə vermək üçün əsas class onu virtual açar sözü ilə işarələyir. Törəmə class isə, implementasiyanı dəyişmək üçün override açar sözündən istifadə edir.

Nümunə


public class Animal
{
    public string Name { get; set; }
    public virtual void MakeSound()
    {
        Console.WriteLine("Hansısa universal heyvan səsi...");
    }
}
        

İndi isə it class-ında:


public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Hav-hav!");
    }
}
        
  • Əsas class-da — virtual.
  • Törəmə class-da — override.
  • Metodun signaturası (adı, qaytarılan tip, parametrlər) eyni olmalıdır.

Vizual sxem

Dog, Animal-dan miras alır və MakeSound()-u yenidən təyin edə bilər

2. İş prinsipi nümayişi

Gəlin baxaq, yenidən təyin etmə necə işləyir. Heyvanlar yaradaq və səslərinə baxaq:

Animal pet1 = new Animal { Name = "Adsız heyvan" };
Dog pet2 = new Dog { Name = "Barbos" };

pet1.MakeSound(); // Çap edəcək: Hansısa universal heyvan səsi...
pet2.MakeSound(); // Çap edəcək: Hav-hav!

İndi isə tapşırığı çətinləşdirək:
Bəs əgər iti Animal tipli dəyişəndə saxlasam?

Animal pet3 = new Dog { Name = "Şarik" };
pet3.MakeSound(); // ???

Necə düşünürsən, nə baş verəcək?
Cavab: "Hav-hav!" çap olunacaq
Çünki dəyişənin tipi Animal olsa da, o "it"-ə işarə edir və çağırılan metodun yenidən təyin olunmuş versiyası işləyəcək!
Budur, dinamik (və ya gec) bağlanmanın magiyası.

3. Yenidən təyin edəndə base açar sözündən istifadə

Bəzən metodu tamamilə əvəzləmək yox, onu genişləndirmək istəyirsən — məsələn, özünü əlavə edib, sonra köhnə davranışı da icra etmək. Bunun üçün base açar sözündən istifadə olunur. O, əsas class-dakı metodun versiyasını çağırmağa imkan verir.


public class Cat : Animal
{
    public override void MakeSound()
    {
        base.MakeSound(); // əsas implementasiyanı çağırır
        Console.WriteLine("Miyau!");
    }
}
        

Bu metodu çağıranda əvvəlcə "Hansısa universal heyvan səsi...", sonra isə "Miyau!" yazılacaq

4. Yenidən təyin etmədə metod seçimi necə işləyir

Gözlə görünən olsun deyə, "qapağın altında" nə baş verdiyini belə bir cədvəldə təsəvvür et (virtual dispatch):

Dəyişənin tipi Obyektin tipi Hansı metod çağırılır
Animal Animal Animal.MakeSound
Animal Dog Dog.MakeSound
Animal Labrador Labrador.MakeSound
Dog Labrador Labrador.MakeSound
Dog Dog Dog.MakeSound

Əsas qayda:
Dəyişənin tipi yalnız compiler üçün vacibdir, icra zamanı isə obyektin faktiki tipi nəzərə alınır (yəni new ilə nə yaratmışıqsa).
Bu mexanizmə dinamik (və ya gec) bağlanma deyilir — məhz bunun üzərində polymorphism qurulur (bunun haqqında — növbəti dərsdə!).

Metodları niyə yenidən təyin edirik

  • GUI framework-lərdə: əsas pəncərə class-ın var, və konkret elementləri çəkmək üçün metodları yenidən təyin edirsən.
  • Oyun engine-lərində: əsas Enemy class-ı, törəmə class-lar isə fərqli davranışlar implementasiya edir.
  • Unit test-lərdə: metodlar üçün "stub" və ya "mock" yarada bilərsən.

Müasir .NET framework-ləri bu mexanizmdən aktiv istifadə edir: event-lər, şablon kod, konfiqurasiyaların miras alınması və hətta obyektlərin serialization-u üçün (məsələn, virtual property-lər vasitəsilə).

5. new açar sözü ilə metodların gizlədilməsi

Artıq bildik ki, metodların yenidən təyin edilməsi üçün virtual/override dueti lazımdır. Amma C#-da irsiyyət iyerarxiyasında metodlarla bağlı başqa bir modifikator da var — bu da new-dur.

new nə üçündür?

new istifadə olunur, əgər törəmə class-da eyni signaturaya malik metod elan edirsənsə, AMMA virtual metodu yenidən təyin etmək yox, məhz gizlətmək (maskalamaq) istəyirsən.

  • Bu, yenidən təyin etmə deyil, gizlətmə-dir.
  • Belə metod dəyişənin tipinə görə çağırılır, obyektin faktiki tipinə görə yox (dinamik polymorphism yoxdur!).
  • Əgər təsadüfən new açar sözü olmadan metodu gizlətsən, compiler xəbərdarlıq edəcək.

Nümunə: override və new fərqi


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

public class Dog : Animal
{
    // Əsas class-dakı metodu gizlədirik (YENİDƏN TƏYİN ETMİRİK)
    public new void MakeSound()
    {
        Console.WriteLine("Bu override deyil! Sadəcə it metodu.");
    }
}
        

İndi isə davranışa baxaq:

Animal a = new Dog();
Dog d = new Dog();

a.MakeSound(); // "Heyvan hansısa səs çıxarır..."
d.MakeSound(); // "Bu override deyil! Sadəcə it metodu."
  • Əgər dəyişənin tipi Dog-dursa — Dog-dakı metod çağırılır.
  • Əgər dəyişənin tipi Animal-dırsa, hətta içində Dog olsa belə — Animal-dakı metod çağırılır!

6. Əks əlaqə və implementasiya xüsusiyyətləri

Proqramlaşdırmanın ilk vaxtlarında çox vaxt belə anlaşılmazlıq olur ki, metod "yenidən təyin olunub", amma nədənsə köhnə kimi işləyir. Adətən səbəb sadədir: əsas class-da virtual yoxdur, ya da törəmə class-da metod new ilə elan olunub, override ilə yox. İkinci hal xüsusilə hiyləgərdir — əgər metodu əsas tipli dəyişənlə çağırsan, əsas versiya işləyəcək, yenidən təyin olunmuş yox. Ona görə həmişə açar sözlərdən düzgün istifadə etdiyinə əmin ol.

Sintaksis səhvlərindən başqa, bəzən yeni başlayanlar yenidən təyin edəndə qaytarılan tipi dəyişməyə çalışırlar. Məsələn, əsas funksiyada qaytarılan tip object, törəmədə isə string etmək istəyirlər. Belə olmaz: metodun signaturası tam uyğun olmalıdır.

Müqayisə cədvəli: override vs new

Xüsusiyyət override new
Mexanizm Virtual metodu yenidən təyin edir Əsas class-dakı metodu gizlədir
Gec bağlanma Bəli — dinamik polymorphism işləyir Xeyr — dəyişənin tipinə görə işləyir
Base-də olmalıdır... virtual, abstract və ya artıq override Xeyr
İstifadə tövsiyəsi Bəli, demək olar həmişə Yalnız istisna hallarda

7. Yenidən təyin olunmuş metodlar və iyerarxiyalar

Bu yenidən təyin etmə mövzusu xüsusilə maraqlı olur, əgər uzun irsiyyət zəncirimiz varsa:


public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Heyvan nəsə edir...");
    }
}

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

public class Labrador : Dog
{
    public override void MakeSound()
    {
        Console.WriteLine("Mən labradoram: vau-vau!");
    }
}
        

Bəs belə yazsaq nə baş verər:

Animal pet = new Labrador();
pet.MakeSound(); //   => "Mən labradoram: vau-vau!"

C# həmişə obyektin üzərində olan ən "dərin" virtual metod implementasiyasını seçəcək.

8. Metodların yenidən təyin edilməsində tipik səhvlər

Dünya ideal deyil, və tələbələr (hətta təcrübəli proqramçılar!) bəzən səhvlər edirlər. Gəlin ən populyar "tələ"lərdən dərhal qaçaq:

1. Əsas class-da virtual unutmuşuq


public class Animal
{
    public void MakeSound() { ... } // 'virtual' yoxdur
}

public class Dog : Animal
{
    // Kompilyasiya səhvi! Yenidən təyin edə bilmirik.
    public override void MakeSound()
    {
        Console.WriteLine("Hav!");
    }
}
        

C# dərhal deyəcək: 'Dog.MakeSound()': override üçün uyğun metod tapılmadı

2. Signaturalar uyğun gəlmir

Əmin ol ki, metodun adı, qaytarılan tipi və parametrləri eynidir:


public class Animal
{
    public virtual void MakeSound() { ... }
}

public class Dog : Animal
{
    // Səhv: signatura fərqlidir (məsələn, parametr əlavə olunub)
    public override void MakeSound(string sound)
    {
        Console.WriteLine(sound);
    }
}
        

3. new əvəzinə override istifadə etməyi unutma

new açar sözü əsas class-dakı metodu gizlətməyə imkan verir, amma bu yenidən təyin etmə deyil və dinamik polymorphism işləmir. Bu başqa bir mexanizmdir və adətən ciddi səbəb olmadan istifadə edilməməlidir.

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