Herkese merhaba. C# yazı dizimdeki en önemli konuya, kalıtıma geldik. Kalıtım bir class’ı temel alarak ondan başka class veya class’lar oluşturmamızı sağlar. Bu uygulama içerisinde yeni geliştirme yapılmasını ve bakımını oldukça kolaylaştırır.  Kendisinden bir başka class türetilen class’a base class denir. Base class’ın içerisinde bulunan bütün property ve metotlara türetilen class içerisinden erişim sağlayabiliriz. Ayrıca türetilen class içerisine kendine has property ve metotlar yerleştirebiliriz. Ortak özelliğe sahip nesnelerimiz varsa her birisi için aynı propertyleri tanımlamak yerine ortak özellikleri içeren bir base class oluşturabiliriz.

Kalıtım (Inheritance)

Örnek olarak hayvanları ele alalım. Kedi ve köpek classlarımızı oluşturalım.

public class Cat
{
    public int Legs { get; set; }
    public int Age { get; set; }

    public string Purr()
    {
        return "Meow!";
    }

    public string StayInside()
    {
        return "I'm staying inside. Purr!";
    }

}

public class Dog
{
    public int Legs { get; set; }
    public int Age { get; set; }

    public string Bark()
    {
        return "Woof!";
    }

   public string GoOutside()
   {
       return "I'm going to outside. Woof!";
   }
}

static void Main(string[] args)
{
    #region Non Inheritance
    Dog dog = new Dog();
    dog.Name = "Odie";
    dog.Legs = 4;
    dog.Age = 2;
    Console.WriteLine("Name : " + dog.Name);
    Console.WriteLine(dog.Bark());
    Console.WriteLine(dog.GoOutside());

    Cat cat = new Cat();
    cat.Name = "Garfield";
    cat.Legs = 4;
    cat.Age = 2;
    Console.WriteLine("Name : " + cat.Name);
    Console.WriteLine(cat.Purr());
    Console.WriteLine(cat.StayInside());
    #endregion

    Console.ReadKey();
}

Gördüğünüz gibi her iki hayvanın da pati sayısı ve yaşı gibi ortak özellikleri var. Her ikisinde de kendilerine ait sesleri çıkartmaları için bir metot bulunuyor. Daha sonra projeye başka bir hayvan dahil etmek istediğimizi farz edelim. Bu durumda onun classında da ortak özellikleri ve ses çıkartma metodunu yeniden tanımlamam gerekiyor. Ayrıca başka bir ortak özellik veya metot eklemek istediğimde de hepsinin içerisinde düzenleme yapmalıyım.

Gerçek hayat projelerinde model sayısının fazlalığı bu şekilde tek tek güncelleme yapılmasını oldukça karmaşıklaştırıyor. Bu nedenle bütün modellerin içerebileceği özelliklere ve metotlara sahip bir base class yaratıp, bu class üzerinden güncelleme işlemlerimizi gerçekleştiriyoruz.

public class Animal
{
    public string Name { get; set; }
    public int Legs { get; set; }
    public int Age { get; set; }

    public string MakeNoise(string noise)
    {
        return noise;
    }
}

public class CatInherited : Animal
{
    public string StayInside()
    {
        return "I'm staying inside. Purr!";
    }

}

public class DogInherited : Animal
{
   public string GoOutside()
   {
       return "I'm going to outside. Woof!";
   }
}

static void Main(string[] args)
{
    DogInherited dogInherited = new DogInherited();
    dogInherited.Name = "Odie";
    dogInherited.Legs = 4;
    dogInherited.Age = 2;
    Console.WriteLine("Name : " + dogInherited.Name);
    Console.WriteLine(dogInherited.MakeNoise("Woof!"));
    Console.WriteLine(dogInherited.GoOutside());

    CatInherited catInherited = new CatInherited();
    catInherited.Name = "Garfield";
    catInherited.Legs = 4;
    catInherited.Age = 2;
    Console.WriteLine("Name : " + catInherited.Name);
    Console.WriteLine(catInherited.MakeNoise("Meow!"));
    Console.WriteLine(catInherited.StayInside());

    Console.ReadKey();
}

Kalıtım kullanarak her iki hayvanda bulunan özellikleri Animal class’ı altında toparladık. Dışarı çıkma metodu köpeğe özgü, içeride kalma metodu da kediye özgü bir metot olduğu için bunları yine altında tanımladık. Base class’ı kendinden türeyen sınıflarla tanımlayarak kullanabiliriz. Ancak türeyen sınıfların içerisinde oluşturduğumuz metotlara erişim sağlayamayız.

static void Main(string[] args)
{
    Animal animal = new CatInherited();
    animal.Name = "Felix";
    animal.Legs = 4;
    animal.Age = 5;
    Console.WriteLine("Name : " + animal.Name);
    Console.WriteLine(animal.MakeNoise("Purr!"));
    Console.WriteLine(animal.StayInside());

    Console.ReadKey();
}

StayInside metodu Animal class’ında bulunmadığından dolayı hata verecek ve kod derlenemeyecek. Bu durumda cast işlemi yaparak türemiş sınıf metotlarına erişim sağlayabiliriz.

Constructor (Yapıcı) Metotlar

Constructor metotlar sınıfın yeni bir üyesi oluştuğunda çalışacak olan ilk metottur. Sınıfıyla tam olarak aynı ada sahiptir, publictir ve herhangi bir dönüş türü yoktur. Sınıfta constructor metot oluşturulmazsa varsayılan constructor metot oluşturulur. Varsayılan bir constructor metodunun parametresi yoktur. Gerekirse, constructor metoda parametreler eklenebilir. Nesne oluşturulduğunda nesneye bir başlangıç ​​değeri atamayı sağlar. Bu yönteme class initializer denir.

static void Main(string[] args)
{
    CatInherited cat2 = new CatInherited() { 
        Name = "Kitty",
        Legs = 4,
        Age = 1
    };

    Console.WriteLine("Name : " + cat2.Name + " Age: " + cat2.Age);

    Console.ReadKey();
}

Kalıtım aşamasında constructor metotlar aşağıdaki adımları izler.

  1. Constructor metotlar fiziksel olarak türetilemez.
  2. Türetilen sınıftan nesne yaratıldığında önce ana sınıfın parametre almayan constructor metodu, ardından türetilen sınıftaki imzaya uyan constructor metot çalışır.
  3. Daima türetilen sınıfın imzaya uyan bir constructor metodu olması gerekir.
  4. Ana sınıfın parametre almayan constructor metodu türetilen sınıfın üye elemanlarıyla işlem yapar.
  5. Türetilen sınıfta ilgili (imzası kalıtım alınan sınıfın constructor metoduna uygun) constructor metoda base takısı eklenirse ilk önce kalıtım alınan sınıfın constructor metodu çalışır.

Şimdi bu aşamaları kod ile örneklendirelim.

public class Vehicle
{
    public Vehicle()
    {
        Console.WriteLine("Vehicle constructor çalıştı!");
    }
}

public class Car : Vehicle
{
    //public Car()
    //{
    //    Console.WriteLine("Car constructor çalıştı!");
    //}

    public Car(string message)
    {
        Console.WriteLine(message);
    }
}

static void Main(string[] args)
{
    //Car car = new Car();
    Car car = new Car("Hello car!");

    Console.ReadKey();
}

Önce ana sınıfın constructor metodu çalıştı. Daha sonrasında türetilen sınıfın constructor metodu çalıştı.

public class Vehicle
{
    public Vehicle()
    {
        Console.WriteLine("Vehicle constructor çalıştı!");
    }
}

public class Car : Vehicle
{
}

static void Main(string[] args)
{
    Car car = new Car();

    Console.ReadKey();
}

Constructor Varsayilan ConstructorVarsayılan constructor metodu ana sınıftaki constructor metodunun imzasına uygun olduğu için herhangi bir şekilde hata vermeden çalıştı.

 

5. kuralı uygulamamız için base() yardımcı metoduna ihtiyacımız var. Kalıtım aldığımız sınıfın constructor metodunu manuel bir şekilde tetiklemek için kullanabiliriz. Örneğin Vehicle sınıfında 2 adet constructor metodu bulunuyor. Base yardımcı metodunu kullanarak Car classı içerisinden string parametre alan Vehicle constructor metodunu çağırabiliriz. (Base metodu içerisine parametreyi vermeden çağırırsak ana sınıftaki imzaya uygun olan constructor metodunu çalıştırır.)

public class Vehicle
{
    public Vehicle()
    {
        Console.WriteLine("Vehicle constructor çalıştı!");
    }

    public Vehicle(string message)
    {
        Console.WriteLine(message);
    }
}

public class Car : Vehicle
{
    public Car() : base("Hello vehicle!")
    {
        Console.WriteLine("Car constructor çalıştı!");
    }
}

static void Main(string[] args)
{
    Car car = new Car();

    Console.ReadKey();
}

Base Yardımcı Metot Çalışma Sırası

Destructor (Yıkıcı) Metotlar

Destructor metotlar constructor metotların tam zıttı şekilde çalışır. Bir nesne silindiğinde ya da yok olduğunda otomatik olarak tetiklenir ve bir sınıfın sadece bir yıkıcı metodu olur. Yıkıcı metotlar dışarıdan çağırılamazlar, otomatik bir şekilde çalışırlar. Erişim belirleyici ya da parametre almazlar. Metot ismi ~ ile başlamak zorundadır.

public class Vehicle
{
    public Vehicle()
    {
        Console.WriteLine("Vehicle constructor çalıştı!");
    }

    public Vehicle(string message)
    {
        Console.WriteLine(message);
    }
}

public class Car : Vehicle
{
    public Car() : base("Hello vehicle!")
    {
        Console.WriteLine("Car constructor çalıştı!");
    }

    ~Car()
    {
        Console.WriteLine("Car objesi yok oldu!");
    }
}

static void Main(string[] args)
{
    GetCar();
    GC.Collect(); //destructor metodun çağrılması için garbadge collector kullanıyoruz.

    Console.ReadKey();
}

private static void GetCar()
{
    Car car = new Car();
}

Destructor Metot Kullanımı

Kalıtım ile ilgili önemli bulduğum bütün bilgileri bu yazıda bir araya getirmeye çalıştım. Bir sonraki yazıya kadar kendinize çok iyi bakın! 😊