Herkese merhaba. Nesne yönelimli programlamanın ana başlıklarından biri olan polymorphism konusunu inceleyeceğiz. Bazen içeride farklı işlemler yapılsa bile aynı sonucu döndüren metotlara ihtiyacımız olur. Aynı kodu tekrar tekrar yazmak bir süre sonra projenin inanılmaz boyutlara ulaşmasına neden olur. Nesne yönelimli programa metodolojisinde de bu sorunu çözmek için çok biçimlilikten faydalanırız. Çok biçimlilik, temelde aynı tür olan metotların farklı davranması gerektiğinde kullanıldığımız bir yöntemdir. Örneklere github reposundan ulaşabilirsiniz.

Çok Biçimlilik (Polymorphism)

Yukarıda da belirttiğim gibi polymorphism, aynı türde ancak içerisinde farklı işlemler yapılabilen metotlar oluşturmamızı sağlar. Örneğin; genel bir sınıf olan hayvanları ele alalım. Kalıtımdan öğrendiğimiz üzere projemizin içerisine bir Hayvan classı oluşturacağız. Bütün hayvanların farklı özellikleri olsa da hepsinin ses çıkarma yeteneğine sahip olması gerekir. Bu şekildeki bir ortak yeteneği Hayvan classı içerisinde ortaklaştırabiliriz.

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

    public virtual string MakeNoise()
    {
        return "Animal";
    }
}

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

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

    public override string MakeNoise()
    {
        return "Woof!";
    }
}

static void Main(string[] args)
{
    Dog dog1 = new Dog();
    Console.WriteLine(dog1.MakeNoise());

    Cat cat1 = new Cat();
    Console.WriteLine(cat1.MakeNoise());

    Console.ReadKey();
}

Örnekte göreceğiniz üzere her iki class içerisinde de aynı metodu çağırdık ancak iki hayvan da farklı sesler çıkartmaktadır. Bu metodu base class içerisinde yazmasaydık her oluşturduğumuz sınıfın içerisinde bu ortak özelliği yazmak zorunda kalacaktık. Özellikle büyük çaplı projelerde bu tekrarlar çok fazla performans kaybına neden olabilir.

C# içerisinde tekrar kullanacağımız metotları base class içerisinde virtual keywordü ile işaretleriz. Bu metodu başka sınıflar içerisinde çağıracağımız zaman override yazmamız gerekir. Eğer override etmeden aynı metodu kullanmaya çalışırsak proje yine derlenmektedir. Visual studioda proje geliştiriyorsanız aşağıdaki uyarıyı alabilirsiniz.

Polymorphism Uyarı

Main metodundan kedi nesnesi üretildiğinde ilk önce base class tetiklenmektedir. Burada virtual ibaresi bu metodun özelleştirileceğini belirtiyor. Bu sayede kedi sınıfı içerisinde verdiğimiz override metot çalışıyor. Virtual metotlar bir grup ilişkili nesnelerle tek tip bir şekilde çalışmamıza yardımcı olur. Her sınıf aynı metodu kendi yöntemi ile kullanır.

Propety ve Polymorphism

Polymorphism, sadece metotlar için kullanılamaz. Propertyleri de virtual ile işaretleyerek daha sonrasında override edebiliriz. Örneğin; bir iş uygulaması olsun ve çalışanların maaşlarını bu uygulama üzerinden yönetelim. Temel olarak bir personel sınıfı oluşturup bunun özelliklerini tanımlayalım.

internal class Staff
{
    public string Name { get; set; }
    public string Lastname { get; set; }
    public int WorkDays { get; set; }
    public decimal DailyWage { get; set; }

    public virtual decimal Salary
    {
        get
        {
            return WorkDays * DailyWage;
        }
    }
}

Maaş özelliğini virtual yaparak diğer classlar içerisinde düzenlenebilmesini sağladık. Örneğin işçi çalışılan gün * günlük ücret’in 2 katını alırken yöneticiler 5 katını alabilir. Bunun için bu iki classı oluştururken maaş özelliğini override etmemiz gerekir.

internal class Worker : Staff
{
    public override decimal Salary
    {
        get
        {
            return DailyWage * WorkDays * 2;
        }
    }
}

internal class Manager : Staff
{
    public override decimal Salary
    {
        get
        {
            return DailyWage * WorkDays * 5;
        }
    }
}

internal class Intern : Staff
{
}

Main program üzerinden bu classların nesnelerini çağırarak hesaplamaların nasıl değiştiğini görelim.

static void Main(string[] args)
{
    Staff staff= new Staff();
    staff.Name = "Biff";
    staff.Lastname = "Tannen";
    staff.DailyWage = 10;
    staff.WorkDays = 20;

    Worker worker = new Worker();
    worker.Name = "Marty";
    worker.Lastname = "McFly";
    worker.DailyWage = 10;
    worker.WorkDays = 20;

    Manager manager = new Manager();
    manager.Name = "Emmett";
    manager.Lastname = "Brown";
    manager.DailyWage = 10;
    manager.WorkDays = 20;

    Intern intern = new Intern();
    intern.Name = "Lorraine";
    intern.Lastname = "Baines";
    intern.DailyWage = 10;
    intern.WorkDays = 20;

    Console.WriteLine("Staff: " + staff.Name + " " + staff.Lastname + " Salary: " + staff.Salary);
    Console.WriteLine("Staff: " + worker.Name + " " + worker.Lastname + " Salary: " + worker.Salary);
    Console.WriteLine("Staff: " + manager.Name + " " + manager.Lastname + " Salary: " + manager.Salary);
    Console.WriteLine("Staff: " + intern.Name + " " + intern.Lastname + " Salary: " + intern.Salary);

    Console.ReadKey();
}

Görüldüğü gibi Intern sınıfından üretilen nesnenin maaş hesaplaması yapılırken Salary property’si override edilmediği için staff nesnesi ile aynı maaşa sahip. Worker nesnesi, staff nesnesinden gelen Salary property’sini override ettiği için 2 katı maaşa sahip.

Override ve Polymorphism Farklılıkları

Override işlemi, bir nesne üzerinde bir metodu çağırdığınızda ve üst sınıftakiyle aynı imzaya sahip metodun çağrılmasıdır. Metodun içerisini o sınıfın ihtiyaçları doğrultusunda doldurabiliriz.

Polymorphism, runtimeda nesnelerin türünden emin olmadığınız ve en spesifik metodun çağrıldığı yerdir. Bu nedenle, çağrılan metodun davranışı, çalışma zamanında nesne türüne bağlı olarak farklılık gösterebilir. Override işlemi Polymorphismin bir alt dalıdır.

Polymorphism ile ilgili bildiklerimi bir araya getirmeye çalıştım. Bir sonraki yazıya kadar kendinize çok iyi bakın! 😊