CodeGym /Kurslar /C# SELF /Konstruktorların overload olunması

Konstruktorların overload olunması

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

1. Giriş

Tutaq ki, bizdə Person adlı class var:

public class Person
{
    public string Name;
    public int Age;
    
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

Və sən artıq özünü demək olar ki, dahiyanə hiss edirsən — istənilən ad və yaşla insan yarada bilərsən. Amma problem budur: bəzən məlumat çatışmır! App istifadəçisi sadəcə ad daxil edib, yaş isə nədənsə bir az sonra məlum olur. Və ya bəzən "default" yaş təyin etmək istəyirsən. Əlbəttə, workaround fikirləşmək olar, amma C# bu iş üçün elegant həll verir — konstruktorların overload olunması.

Konstruktorların overload olunması o deməkdir ki, bir class-da eyni adda bir neçə konstruktor (class-ın adı ilə) ola bilər, amma fərqli parametrlər siyahısı ilə.

Bu siyahılar nədə fərqlənir? Onlar aşağıdakılara görə fərqlənə bilər:

  1. Parametrlərin sayı: Məsələn, bir konstruktor 2 parametr alır, digəri — 3.
  2. Parametrlərin tipi: Biri (string, int) alır, digəri — (string, decimal).
  3. Parametrlərin sırası: (string, int)(int, string) — fərqli signature-lardır.

Ən əsas qayda: compiler konstruktorları (və ümumiyyətlə metodları) onların signature-na görə fərqləndirir. Signature — konstruktorun (və ya metodun) adı və parametrlər siyahısıdır (sayı, tipləri və sırası). Access modifier-lər (public, private) və adi metodlar üçün return type signature-a daxil deyil. Amma konstruktorlarda return type olmur, adı isə həmişə class-ın adı ilə eynidir.

2. Konstruktorların overload olunması: sintaksis və nümunə


public class Cat
{
    public string Name;
    public string Color;

    // Parametrsiz konstruktor
    public Cat()
    {
        Name = "Adsız pişik";
        Color = "Boz";
    }

    // Bir parametrli konstruktor
    public Cat(string name)
    {
        Name = name;
        Color = "Boz";
    }

    // İki parametrli konstruktor
    public Cat(string name, string color)
    {
        Name = name;
        Color = color;
    }
}

İstifadə:

Cat barsik = new Cat(); // "Adsız pişik", "Boz"
Cat murzik = new Cat("Murzik"); // "Murzik", "Boz"
Cat ryzhik = new Cat("Rijik", "Rijiy"); // "Rijik", "Rijiy"

Əgər obyekt yaradanda parametrləri göstərirsənsə, C# onların sayına və tipinə görə düzgün konstruktoru "tapacaq".

Bu çox rahatdır! Sənin class-ından istifadə edən adam bilmədiyi parametrləri yazmağa məcbur deyil: sadəcə pişik istəyirsə — parametrsiz konstruktoru seçir, adı bilirsə — o birini, və s. Rəngə tam nəzarət lazımdırsa — üçüncü variantı seçir.

3. Overload olunmuş konstruktorların çağırılması necə işləyir?

C# lazım olan konstruktoru avtomatik olaraq compile zamanı seçir, ötürülən arqumentlərin tipinə və sayına görə. Səhv etmək çətindir — nəsə qarışdırsa, compiler dərhal sərt xəbərdarlıq edəcək.

Gəlin bir dənə tam ədədli parametrli konstruktor əlavə edək:

public Cat(int age)
{
    Name = "Adsız pişik";
    Color = "Boz";
    // Yaş üçün əlavə kod
}

İndi artıq "yaşa görə pişik balası" da yarada bilərik:

Cat oldCat = new Cat(5); // Cat(int age) konstruktoru çağırılacaq
Konstruktorun çağırılması Hansını çağıracaq?
new Cat()
Parametrsiz
new Cat("Murka")
Bir string parametrli
new Cat("Rijik", "Rijiy")
İki string parametrli
new Cat(10)
Bir tam ədədli parametrli

4. Konstruktorların daxilində bir-birini çağırması: this açar sözü

Bəzən müxtəlif konstruktorlar oxşar (və ya eyni) işi görür. Kodu təkrarlamamaq üçün bir konstruktoru digərindən çağırmaq olar. Bunun üçün this açar sözü istifadə olunur.


public class Cat
{
    public string Name;
    public string Color;

    public Cat() : this("Adsız pişik")
    {
        // Bu konstruktor Cat(string name) çağırır
    }

    public Cat(string name) : this(name, "Boz")
    {
        // Bu konstruktor Cat(string name, string color) çağırır
    }

    public Cat(string name, string color)
    {
        Name = name;
        Color = color;
    }
}

Nəticədə:

  • new Cat() Cat(string name) çağırır, o isə Cat(string name, string color) çağırır.
  • Bütün "yollar Romaya aparır": yəni bütün initialization bir "əsas" konstruktorda toplanır.

Bu yanaşmaya constructor chaining (konstruktorların zənciri) deyilir.

5. Həyatdan nümunələr

Gəlin oyun üçün qəhrəman (Hero) class-ı yaradaq, adı və səviyyəsi olsun! Bax belə yazardıq:

Bir konstruktorla:

public class Hero
{
    public string Name;
    public int Level;

    public Hero(string name, int level)
    {
        Name = name;
        Level = level;
    }
}

İndi isə gəlin onu müxtəlif cür yaratmağa imkan verək!

Çoxlu konstruktorlarla:

public class Hero
{
    public string Name;
    public int Level;

    // Heç nə göstərilməsə, qəhrəman "Adsız 1-ci səviyyə" olsun
    public Hero() : this("Adsız", 1)
    {
    }

    // Yalnız ad bilinir, səviyyə default — 1
    public Hero(string name) : this(name, 1)
    {
    }

    // Ən əsas konstruktor iki parametrlə
    public Hero(string name, int level)
    {
        Name = name;
        Level = level;
    }
}

İndi qəhrəmanı müxtəlif üsullarla yaratmaq olar:

Hero h1 = new Hero();               // "Adsız", 1
Hero h2 = new Hero("Artur");        // "Artur", 1
Hero h3 = new Hero("Lora", 10);     // "Lora", 10

6. Reallaşdırma detalları: gizli tələlər və nüanslar

Birinci: əgər sən özün hər hansı konstruktor yazmısansa, compiler artıq "boş" konstruktoru default olaraq yaratmır. Yəni, parametrli konstruktor yazıb, parametrsiz konstruktor əlavə etməyi unutsan, belə çağırış:

Hero h = new Hero(); // Səhv, əgər parametrsiz konstruktor yoxdursa!
compile error verəcək.

İkinci: konstruktorların chain-lərində səhv konstruktoru çağırsan, initialization məntiqi pozula bilər. Konsistentlik vacibdir: ən yaxşısı, bütün real iş əsas, ən tam konstruktorda olsun, qalanları isə this(...) ilə ora ötürsün.

Üçüncü: əgər parametrlər yalnız tiplərinə görə fərqlənirsə (məsələn, Cat(string s)Cat(object o)), konstruktoru null arqumenti ilə çağıranda qarışıqlıq ola bilər. Compiler həmişə başa düşməyə bilər ki, hansını çağırmaq istəyirsən.

7. Overload və field-ların initialization-ı

Çox vaxt class-da mütləq təyin olunmalı field-lar olur. Konstruktorların overload olunması bunu rahat etməyə kömək edir, amma hansı default dəyərlərin sənin class-ın üçün məntiqli olduğunu sən özün seçirsən.

Yoxlama ilə nümunə:

public class Book
{
    public string Title;
    public int Year;

    // Default kitab — "Adsız", 2000-ci il
    public Book() : this("Adsız", 2000)
    {
    }
    
    public Book(string title) : this(title, 2000)
    {
    }

    public Book(string title, int year)
    {
        Title = title;
        Year = year;
    }
}

8. Müxtəlif parametr dəstləri ilə overload

Bəzən class-larda konstruktorların sayı onlarla olur! Bu həmişə yaxşı arxitektura əlaməti deyil (bəzən "setup" metodları və ya "builder" pattern-i daha yaxşıdır), amma istifadəçi obyektləri, modellər, DTO üçün — tam işlək variantdır.

Nümunə: "Ev heyvanı" class-ı, burada bütün xüsusiyyətləri açıq göstərmək olar, ya da yalnız ən vaciblərini.

public class Pet
{
    public string Name;
    public int Age;
    public string Type;
    public bool IsVaccinated;

    // Default konstruktor
    public Pet() : this("NoName", 0, "Cat", false) { }

    // Minimum məlumat
    public Pet(string name, string type) : this(name, 0, type, false) { }

    // Tam konstruktor
    public Pet(string name, int age, string type, bool isVaccinated)
    {
        Name = name;
        Age = age;
        Type = type;
        IsVaccinated = isVaccinated;
    }
}
Metodun overload olunması ilə konstruktorun overload olunması arasındakı fərq
Adi metod Konstruktor (o cümlədən overload olunmuş)
İstənilən vaxt çağırmaq olar Yalnız obyekt yaradanda çağırılır (new)
İstənilən tipdə dəyər qaytara bilər Heç vaxt dəyər qaytarmır (tip göstərilmir)
Metodun adı istənilən ola bilər, adətən fel olur Adı həmişə class-ın adı ilə eynidir
Parametrlərə görə overload etmək olar Eləcə də parametrlərə görə overload olunur
1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
Sinif və obyekt anlayışı
Siniflər və konstruktorlar
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION