1. Giriş
Bugünkü mövzu bir az abstrakt görünə bilər, amma inan, onsuz heç yerə gedə bilmərik. Biz irsilik haqqında danışacağıq. Bu gün sadəcə bir az toxunacağıq, gələcəkdə isə daha detallı baxacağıq.
Təsəvvür elə, sən zooparkda heyvanların uçotu üçün proqram yazırsan. Səndə müxtəlif heyvan növləri var: şirlər, pələnglər, fillər, tutuquşular. Onların hamısı — heyvandır. Amma onların öz xüsusiyyətləri də var:
- Şirin yelesi var.
- Pələng zolaqlıdır.
- Fil çox böyükdür və xortumu var.
- Tutuquşu danışa bilir.
Əgər hər heyvanı ayrıca təsvir etsəydik, kod çox oxşar olardı:
// Şir
public class Lion
{
public string Name { get; set; }
public int Age { get; set; }
public string Species { get; set; } = "Şir"; // Həmişə "Şir"
public void Eat() { Console.WriteLine("Şir ət yeyir."); }
public void Sleep() { Console.WriteLine("Şir yatır."); }
public void Roar() { Console.WriteLine("Şir nərildəyir!"); }
public string ManeColor { get; set; } // Şirin xüsusiyyəti - yelesi
}
// Pələng
public class Tiger
{
public string Name { get; set; }
public int Age { get; set; }
public string Species { get; set; } = "Pələng"; // Həmişə "Pələng"
public void Eat() { Console.WriteLine("Pələng ət yeyir."); }
public void Sleep() { Console.WriteLine("Pələng yatır."); }
public void Stride() { Console.WriteLine("Pələng səssizcə addımlayır."); }
public string StripePattern { get; set; } // Pələngin xüsusiyyəti - zolaqlılıq
}
Görürsən, nə qədər təkrarlanan kod var? Name, Age, Eat(), Sleep() — bunlar bütün heyvanlar üçün ortaqdır! Bəs 100 növ heyvan olsa? Dəhşət!
Bax, burada bizə irsilik kömək edir.
2. C#-da class irsiliyi nədir?
İrsilik — obyekt yönümlü proqramlaşdırmanın (OOP) əsas prinsiplərindən biridir. Bu, yeni class-ları artıq mövcud olanların əsasında yaratmağa imkan verir. Yeni class (irs alan, uşaq class, törəmə class) öz valideyn class-ının (əsas class, valideyn class) bütün xüsusiyyətlərini (sahələrini) və davranışını (metodlarını) alır (irs alır).
Bu, real həyatda olduğu kimi: sən valideynlərindən hansısa xüsusiyyətləri irs alırsan, amma sənin özünəməxsus cəhətlərin də var.
C#-da irsilik iki nöqtə : ilə göstərilir, uşaq class adından sonra yazılır:
// Valideyn (əsas) class - Animal
public class Animal
{
public string Name { get; set; } // Heyvanın adı
public int Age { get; set; } // Heyvanın yaşı
public void Eat()
{
Console.WriteLine($"{Name} yeyir.");
}
public void Sleep()
{
Console.WriteLine($"{Name} yatır.");
}
}
// Uşaq (törəmə) class - Lion, Animal-dan irs alır
public class Lion : Animal // <-- Bax budur, irsilik!
{
public string ManeColor { get; set; } // Şirin unikal xüsusiyyəti
public void Roar() // Şirin unikal davranışı
{
Console.WriteLine($"{Name} nərildəyir: RRRRRR!");
}
}
// Daha bir uşaq class - Tiger, Animal-dan irs alır
public class Tiger : Animal
{
public string StripePattern { get; set; } // Pələngin unikal xüsusiyyəti
public void Stride() // Pələngin unikal davranışı
{
Console.WriteLine($"{Name} səssizcə addımlayır.");
}
}
İndi, əgər biz Lion və ya Tiger obyektini yaratsaq, onların avtomatik olaraq Name və Age xüsusiyyətləri, həmçinin Eat() və Sleep() metodları olacaq, çünki onlar bunları Animal-dan irs alıblar.
class Program
{
static void Main(string[] args)
{
Lion simba = new Lion();
simba.Name = "Simba";
simba.Age = 5;
simba.ManeColor = "Qızılı";
simba.Eat(); // Animal-dan irs alınan metod
simba.Sleep(); // Animal-dan irs alınan metod
simba.Roar(); // Lion-un öz metodu
Console.WriteLine($"{simba.Name} - yaş: {simba.Age}, yelenin rəngi: {simba.ManeColor}");
Tiger shereKhan = new Tiger();
shereKhan.Name = "Şerxan";
shereKhan.Age = 7;
shereKhan.StripePattern = "Klassik";
shereKhan.Eat(); // Animal-dan irs alınan metod
shereKhan.Sleep(); // Animal-dan irs alınan metod
shereKhan.Stride(); // Tiger-in öz metodu
Console.WriteLine($"{shereKhan.Name} - yaş: {shereKhan.Age}, naxış: {shereKhan.StripePattern}");
}
}
Irsiliyin əsas ideyaları:
- Kodun təkrar istifadəsi (Code Reusability): Ümumi məntiqi əsas class-a yerləşdirərək kod təkrarlanmasından qaçırsan.
- Iyerarxiya (Hierarchy): "Ümumi-xüsusi" məntiqi qurulur (Animal → Lion/Tiger).
- Polimorfizm (Polymorphism): (Hələlik sadəcə qeyd edirik, sonra daha ətraflı olacaq) Sən uşaq class obyektləri ilə əsas class referansı vasitəsilə işləyə bilərsən. Məsələn, Animal siyahısı yaradıb ora həm şir, həm pələng əlavə edə bilərsən və onların Eat() metodunu çağıra bilərsən.
3. Əsas class konstruktorlarının çağırılması (base)
Sən uşaq class obyekti yaradanda (məsələn, new Lion()), C# avtomatik olaraq əsas class-ın konstruktorunu (bizim halda Animal) əvvəl çağırır, sonra uşaq class-ın konstruktorunu çağırır. Bu, obyektin əsas hissəsinin düzgün inicializasiya olunmasına zəmanət verir.
Bəzən əsas class konstruktoruna parametrlər ötürmək lazım olur. Bunun üçün uşaq class konstruktorunun imzasından sonra base açar sözü istifadə olunur.
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
// Əsas class konstruktoru
public Animal(string name, int age)
{
Name = name;
Age = age;
Console.WriteLine($"Animal konstruktoru: Heyvan yaradıldı {Name}, yaş {Age}.");
}
public void Eat()
{
Console.WriteLine($"{Name} yeyir.");
}
public void Sleep()
{
Console.WriteLine($"{Name} yatır.");
}
}
public class Lion : Animal
{
public string ManeColor { get; set; }
// Lion konstruktoru, əsas class Animal konstruktorunu çağırır
public Lion(string name, int age, string maneColor) : base(name, age) // <-- Bax budur, 'base'!
{
ManeColor = maneColor;
Console.WriteLine($"Lion konstruktoru: Yelenin rəngi {ManeColor}.");
}
public void Roar()
{
Console.WriteLine($"{Name} nərildəyir: RRRRRR!");
}
}
class Program
{
static void Main(string[] args)
{
// Lion yaradanda əvvəlcə Animal konstruktoru, sonra Lion konstruktoru çağırılır
Lion simba = new Lion("Simba", 5, "Qızılı");
simba.Roar();
}
}
new Lion("Simba", 5, "Qızılı") icra olunanda nə baş verəcək:
- Lion(string name, int age, string maneColor) konstruktoru çağırılacaq.
- : base(name, age) sayəsində idarəetmə Animal(string name, int age) konstruktoruna ötürüləcək.
- Animal konstruktorunun kodu icra olunacaq və sən Animal konstruktoru: Heyvan yaradıldı Simba, yaş 5. görəcəksən.
- Bundan sonra idarəetmə Lion konstruktoruna qayıdacaq.
- Lion konstruktorunun kodu icra olunacaq və sən Lion konstruktoru: Yelenin rəngi Qızılı. görəcəksən.
Bu çox vacibdir: Əsas class həmişə birinci inicializasiya olunur!
4. is və as operatorları
C#-da proqramlaşdırmada tez-tez obyektin tipini yoxlamaq və ya onu başqa tipə çevirməyə ehtiyacın olacaq. Burada is və as operatorları köməyə gəlir. Onlar xüsusilə irsilik və polimorfizmlə işləyəndə faydalıdır (bu barədə sonra danışacağıq), amma əsaslarını artıq indi başa düşmək olar.
is operatoru (tip yoxlaması)
is operatoru obyektin müəyyən tipə uyğun olub-olmadığını yoxlamağa imkan verir. Əgər obyekt göstərilən tipə çevrilə bilirsə, true qaytarır, əks halda false verir.
Sintaksis: ifadə is Tip
static void AnalyzeObject(object obj)
{
if (obj is string)
{
Console.WriteLine("Bu string-dir!");
}
else if (obj is int)
{
Console.WriteLine("Bu tam ədəddir!");
}
else
{
Console.WriteLine("Bu başqa bir şeydir.");
}
}
static void Main()
{
AnalyzeObject("Salam, dünya!"); // Bu string-dir!
AnalyzeObject(123); // Bu tam ədəddir!
AnalyzeObject(3.14); // Bu başqa bir şeydir.
AnalyzeObject(new int[] { 1, 2 }); // Bu başqa bir şeydir.
}
is pattern matching ilə:
Müasir C#-da is yalnız tip yoxlaması üçün yox, həm də tip uyğun gəlirsə, həmin tipdə dəyişən yaratmaq üçün istifadə oluna bilər. Buna "pattern matching" deyilir və kodu daha qısa və rahat edir.
static void AnalyzeObjectWithPatternMatching(object obj)
{
if (obj is string message) // Əgər obj string-dirsə, onu message dəyişəninə yaz
{
Console.WriteLine($"Bu string-dir, uzunluğu: {message.Length}");
}
else if (obj is int number) // Əgər obj int-dirsə, onu number dəyişəninə yaz
{
Console.WriteLine($"Bu ədəddir, 2-yə vurulmuş: {number * 2}");
}
else
{
Console.WriteLine("Tip tanınmadı.");
}
}
static void Main()
{
AnalyzeObjectWithPatternMatching("Nümunə"); // Bu string-dir, uzunluğu: 6
AnalyzeObjectWithPatternMatching(50); // Bu ədəddir, 2-yə vurulmuş: 100
AnalyzeObjectWithPatternMatching(new object()); // Tip tanınmadı.
}
Bu is və pattern matching yanaşması klassik tip çevirmə və null yoxlamasından daha təhlükəsiz və oxunaqlıdır.
as operatoru (təhlükəsiz tip çevirmə)
as operatoru obyekti göstərilən tipə çevirməyə çalışır. Əgər çevirmə mümkündürsə, həmin tipdə obyekt qaytarır. Əgər çevirmə mümkün deyilsə (obyekt uyğun tipdə deyilsə), as null qaytarır, istisna atmır. Buna görə as "təhlükəsiz" çevirmə operatorudur.
Sintaksis: ifadə as Tip
static void ProcessData(object data)
{
string text = data as string; // data-nı string-ə çevirməyə çalışırıq
if (text != null) // Çevirmə uğurlu oldu?
{
Console.WriteLine($"String emalı: {text.ToUpper()}");
}
else
{
Console.WriteLine("Məlumat string deyil.");
}
}
static void Main()
{
ProcessData("hello"); // String emalı: HELLO
ProcessData(123); // Məlumat string deyil.
ProcessData(null); // Məlumat string deyil.
}
as nə vaxt birbaşa çevirmədən (Tip)ifadə üstün tutulur:
- Təhlükəsizlik: Əgər obyektin həqiqətən lazım olan tipdə olduğuna əmin deyilsənsə, as InvalidCastException-dan qaçmağa və əvəzində null almağa imkan verir, bunu yoxlaya bilərsən.
- Referans tiplərlə: as yalnız referans tiplərlə işləyir (class-lar, interface-lər, delegate-lər, massivlər). O, dəyər tipləri üçün (məsələn, int → double) istifadə oluna bilməz.
Vacib: Əgər obyektin həmişə lazım olan tipdə olacağına əminsənsə və ya dəyər tipini çevirmək lazımdırsa, birbaşa çevirmə (Tip)ifadə istifadə et. Əgər çevirmə mümkün deyilsə, birbaşa çevirmə səhv (istisna InvalidCastException) atacaq və bu, proqramın məntiqində səhvdirsə, bəzən istənilən davranışdır.
GO TO FULL VERSION