Templates by BIGtheme NET
Anasayfa / C# / Object Oriented Programming(OOP)

Object Oriented Programming(OOP)

Dünya üzerinde duran kalem ve dahi masa, etrafınıza baktığınızda görebileceğiniz her şeyi bir nesne olarak tanımlamak mümkündür. Dikkat edersek nesneyi anlatırken “tanımlamak” kelimesini kullandık. Buradan anlayabiliriz ki nesne tanımlanmaya ihtiyaç duyan ancak tanımlanarak var olan bir olgudur. Nesneleri birbirinden ayıran özellikleridir.

Örneğin; Elimize kırmızı ve siyah renklerinde iki farklı kalem alıyoruz. Baktığımız zaman ikisi de bir nesnedir ve ikisininde adı kalemdir. Bu yüzden adlandırırken ikisine de kalem nesnesi deriz.

Kalem, elimizdeki nesnelerin adıdır. Buradan anlayabileceğimiz üzere nesnelerimiz tanımlanabilmek için ilk olarak bir isime ihtiyaç duyarlar.
Fakat örneğimizde de olduğu gibi birden fazla nesne aynı isme sahip olabilir ve biz zaman zaman bu nesneleri birbirinden ayırt etme ihtiyacı duyabiliriz.

Örnek üzerinden gidersek; bir yazı yazıyoruz ve kırmızı renkte yazmak istiyoruz, yazı yazdığımız nesnemiz kalem. Elimizde de iki kalem vardı. Yazmak için iki kalemi de kullanabilirim fakat kırmızı renkte yazmak istiyorsam iki kalemden birisini seçmem gerekiyor. İşte tam olarak burada bu iki nesneyi birbirinden ayırt etme ihtiyacımız doğuyor. Bu noktada kalem nesnemizin renk özelliğine bakıyoruz. Buradan da anlıyoruz ki nesneler özellikler barındırır. Nesnelerin adları aynı olsa da özellikleri sayesinde ayırt edilebilir haldedirler fakat bu demek değildir ki aynı ada ve özelliklere sahip iki nesne olamaz. Örneğin; kalemlerimizin ikisi de siyah, aynı uç kalınlığında ve aynı uzunlukta birebir üretilmiş olabilir. Bütün bu benzerlikler o iki nesneyi birbirinin kopyası yapsa da biliriz ki ikisi de ayrı ayrı birer nesnedir. İkisi de ayrı ayrı var olmuştur. Eğer renkleri, uç kalınlıkları veya herhangi bir özellikleri farklı olsaydı biz nesnenin bu özelliğine “ayrıştırıcı özellik” derdik ve o nesneyi ayırt etmek için onu kullanırdık.

Tüm özellikleri aynı olan iki nesnede ayrıştırıcı özellikten bahsedemeyiz. Bu durum o iki nesnenin ayrı ayrı birer nesne olduğu gerçeğini değiştirmez. Çünkü ikisi de uzay-düzlem de aynı anda aynı yerde bulunamazlar. İkisinin varlığı ayrı devam etmektedir. Sadece birbirinden ayırmak mümkün değildir. Fakat cümleye dikkat edersek “uzay-düzlemdeki konumlarını” da bir özellik olarak alıp bu iki kalem nesnesini renk, uç kalınlığı, uzunluk gibi durumlara bakmadan sadece uzay-düzlemdeki konumlarına göre ayırt edebiliriz.

Günlük hayatta tabi ki x,y uzay düzleminde x,y kordinatlarında z yüksekliğe sahip kalem nesnesi diye bir cümle kurmayız. Fakat deriz ki sağdaki kalem, soldaki kalem, masanın kenarındaki kalem, masanın ortasındaki kalem, kalemlikte ki kalem şeklinde aynı özelliklere sahip kalemleri konum özellikleriyle ayırt edebiliriz. Peki, iki kalemde aynı yerde var olabilir mi? Hayır. İki kalemde üst üste konularak masanın ortasına konulsa bile birisi diğerinin üstüne konulduğundan uzay-düzlem bazında yükseklik farkları olduğundan aynı anda aynı yerde varolamadıkları gerçeği değişmiyor.

Kısaca özetleyecek olursak; nesnelerin özellikleri vardır. Kimi özellikleri farklı olup ayırt edici olabilir fakat tam tersi tüm özellikleri aynı olsa da nesneler tek başlarına, diğerlerinden ayrı olarak varolurlar.


Class (Sınıf) Nedir?

Nesnelerin tanımlanan, isimleri ve özellikleri olan birer yapı olduğunu biliyoruz. Nesneleri ve özelliklerini tanımlarken kullandığımız referans yapı sınıftır.

Bir kalem tanımlayacağız, rengi siyah, uç tipi 2B, uzunluğu 10cm olacak. Bu kalemi ancak içerisinde renk, uç tipi, uzunluk özelliklerini barındıran ve bunları kullanarak “kalem” oluşturacak bir sınıfı kullanarak oluşturabiliriz. Bu yüzden referans noktamız kalem sınıfı olur. Kalem sınıfını kullanarak, gerekli özelliklerini tanımlayarak ve bu nesneye bir isim vererek bir kalem tanımlayabiliriz.

Sınıflar sadece özellik barındırmazlar içerisinde sahip olduğu kendisine has, onu o yapan bir takım işlevleri barındırırlar. Örneğin; bir kalem yazma işlevine, bir buzdolabı soğutma işlevine, bir telefon arama yapma, sms atma, arama alma, sms alma gibi işlevlere sahiptir. Sınıfın sahip olduğu işlevlere tanımladığımız nesneler üzerinden ulaşırız. Bir nesne bir sınıf kullanılarak tanımlanmadan o sınıfın işlevlerine ulaşmak mümkün değildir. Ortada kalem yoksa yazı yazma işlevi de yoktur.

Bir sınıfın içinde özellikler oluşturmak için değişkenleri, işlevler oluşturmak için ise fonksiyonları (methodlar) kullanırız. O yüzden değişken ve fonksiyon tanımlamaya bakmamız gerekir.

Fonksiyon Tanımlama

Fonksiyonlar çağrıldığında içerisinde tanımlanan görevi yerine getiren kod blogu tanımlamalarıdır. Bir fonksiyon direkt olarak çağrılan yerde bir işlem yapabileceği gibi geriye bir değer döndüren türde de olabilir.

<erişim> <geridönüş> <fonksiyonadi>(<parametretipi><parametre>)
{
    //Kodlar burada tanımlanır.
}
* C# dili baz alınmıştır.
  • Erişim: Sınıf içerisindeki fonksiyonlara ve değişkenlere nasıl ulaşılabilir olacağı belirtilmelidir. Buradaki kural bu fonksiyon veya değişkene nasıl erişileceğini belirtir. Erişim kuralları değişkenlerde de fonksiyonlarda olduğu gibi ön ek olarak belirtilir.
    1. public : Bu erişim koduyla tanımlanmış fonksiyon veya değişkene sınıfın içinden, sınıfın dışından ve diğer sınıflardan erişilebilir, bu değişkenler yeniden tanımlanabilir.
    2. private : Bu erişim koduyla tanımlanmış fonksiyon veya değişkene sadece sınıfın içinden erişilebilir.
    3. protected : Bu erişim koduyla tanımlanmış fonksiyon veya değişken bu sınıfın içinden ve sadece yetkisi olan diğer sınıflar tarafından çağrılabilir.
  • Geri Dönüş: Bu kısımda fonksiyonun varsa geri dönüş değeri yoksa da bunun geri dönüşsüz bir fonksiyon olduğu belirtilir.
    1. Geri dönüşsüz fonksiyonlar için her programlama dilinde kullanılan terim farklıdır. Örn: C#’ta void kullanılır.
    2. Eğer bir geri dönüş varsa geri dönen değerin tipi belirtilmelidir.
    Örn: string, integer, boolean, array vb.
  • Fonksiyon Adı: Fonksiyona verdiğiniz isimdir.
  • Parametre: Parametreler fonksiyonların çağrıldığı yerde fonksiyonun içinde kullanılmak üzere dışarıdan gönderilen değerlerdir. Bir fonksiyon birden fazla parametre alabileceği gibi parametresiz de olabilir. Eğer bir parametre tanımlanacaksa o parametreye bir isim ve o parametrenin tipi belirtilmelidir.
public void ornekFonksiyon(string ornek)
{
   //Geri dönüşsüz bir işlem yapılır.
}

Değişken Tanımlama

Sınıf içinde tanımlanan fonksiyonlar gibi değişkenlerinde tanımlanma kuralı vardır.

<erişim> <değertipi> <değişkenadi>
* C# dili baz alınmıştır.
  • Erişim: Değişkene nasıl erişileceği, alacağı değerler fonksiyon ile aynıdır.
  • Değer Tipi: Değişkenin alacağı değerin türünü belirtiriz.
    Örn: String, Integer, Boolean, Array vb.
  • Değişken Adı: Değişkeni hangi isimle kullanacağımız.
public    string  ornekDegisken;
public    string  renk   = "Siyah";
private   int     sayac  = 0;
protected decimal tutar  = 2.60;

Kurucu ve Yıkıcı İşlevler (Construct — Destruct)

Kurucu ve yıkıcı fonksiyonlar adı üstünde sınıftan bir nesne türetildiğinde ve nesne ile ilgili bir işlem yapılıp nesneden çıkılırken çalışan işlevlerdir.

Kurucu ve yıkıcıların her dilde tanımlanma şekilleri farklıdır. İki dilde inceleyecek olursak;

C# Örneği;

class Matematik
{
   //Kurucu fonksiyon (Construct)
   public void Matematik() 
   {
       Console.WriteLine('Matematik sınıfı kurucusundan selamlar, yıkıcılar ölsün!');
   }
   public int carpma(x,y)
   {
       return (x*y);
   }
   //Yıkıcı fonksiyon (Destruct)
   public void ~Matematik()
   {
       Console.WriteLine('Yıkar geçerim!');
   }
}
Matematik m = new Matematik(); //Ekrana direkt olarak "Matematik sınıfı kurucusundan selamlar, yıkıcılar ölsün!" yazacak.
m.carpma(3,5); // 15
// Yıkar Geçerim!

PHP Örneği;

class Matematik
{
    public function __construct()
    {
        echo 'Matematik kurucusundan selamlar, yıkıcılar ölsün!';
    }
    
    public function carpma($x,$y)
    {
       return ($x*$y);
    }
    
    public function __desctruct()
    {
       echo 'Yıkar geçerim!';
    }
}
$m = new Matematik(); // Matematik kurucusundan selamlar, yıkıcılar ölsün!
$m->carpma(3,5); // 15 
//Yıkar geçerim!

İki dilde de constructor ve destructor fonksiyonların tanımlanma şeklini inceledik. Diğer dillerde daha farklı şekillerde olabilir. Örneğin kafa karıştırıcı olmaması ve rahat anlaşılması için direkt olarak yazı çıktısı almış olsam da esas kullanımı sınıf içindeki değişkenlerin nesne türetme işleminin başlangıcı sırasında varsayılan değerlerle donatılması yada sınıfın kod blogundaki etkinliği sona ererken atanan bu değerlerin sıfırlanması gibi daha sistemsel amaçlar içindir.

Diğer OOP kavramlarına göz atmadan önce kodlarla sınıf ve o sınıftan nesneler oluşturarak, OOP’nin temelini oluşturan “sınıf” ve “nesne” kavramlarını daha iyi kavrayalım.


Class (Sınıf) Oluşturma

C# Örneği;

class kalemlerSinifi
{
      public string renk, marka, uctipi;
      public int uzunluk;
      public void yaziYaz(string yazi)
      {
          Console.WriteLine(yazi);
      }
}

Sınıf’tan Nesne Türetme (Nesne Tanımlama)

// İlk ve ikinci kalem nesnelerini tanımlıyoruz
kalemlerSinifi ilkKalem    = new kalemlerSinifi();
kalemlerSinifi ikinciKalem = new kalemlerSinifi();
ilkKalem.renk       = 'Siyah';
ilkKalem.marka      = 'ABC';
ilkKalem.uctipi     = '2B';
ilkKalem.uzunluk    = 10;
ilkKalem.yaziYaz('Hello World!');
ikinciKalem.renk    = 'Kırmızı';
ikinciKalem.marka   = 'XYZ';
ikinciKalem.uctipi  = '3B';
ikinciKalem.uzunluk = 10;
ikinciKalem.yaziYaz('Merhaba Dünya!');
//Üçüncü kalem nesnesini oluşturuyoruz
kalemlerSinifi ucuncuKalem = new kalemlerSinifi();
ucuncuKalem.renk    = 'Siyah';
ucuncuKalem.marka   = 'ABC';
ucuncuKalem.uctipi  = '2B';
ucuncuKalem.uzunluk = 10;
ucuncuKalem.yaziYaz('Selamun Aleyküm Dünya!');

Örneği incelediğimiz zaman ilkKalem ve ucuncuKalem aynı özelliklere sahip ve aynı sınıftan türetilmiş nesneler fakat bu ikisinin her şeyi aynı olmasına rağmen farklı birer iki nesne olduğunu “ilkKalem” ve “ucuncuKalem” isimleriyle tanımlanmalarından anlayabiliyoruz. Oluşturduğumuz bu nesneleri “Instance” olarak adlandırılıyoruz.

Class (Sınıf) Oluşturma

PHP Örneği;

//Kalemler sınıfını oluşturuyoruz.
class kalemlerSinifi
{
    //Sınıf özelliklerini belirleyecek değişkenleri tanımlıyoruz
    public $renk, $marka, $uctipi, $uzunluk;
    //Sınıf işlevi tanımlıyoruz
    public function yaziYaz($yazi)
    {
        echo $yazi;
    }
}

Sınıf’tan Nesne Türetme (Nesne Tanımlama)

//Yeni bir kalem nesnesi oluşturuyoruz ve ilkKalem değişkenine atıyoruz.
$ilkKalem = new kalemlerSinifi();
//Kalem nesnesinin özelliklerini tanımlıyoruz
$ilkKalem->renk    = 'Siyah';
$ilkKalem->marka   = 'ABC';
$ilkKalem->uctipi  = '2B';
$ilkKalem->uzunluk = 10;
//Kalem nesnesinin yaziYaz işlevini kullanıyoruz.
$ilkKalem->yaziYaz('Merhaba Dünya!');

Soyutlama (Abstraction)

Nesne tanımlarken, tanımlayacağımız nesnenin özellik ve işlevlerini o sınıfın nesnesinden aldık. İşte tıpkı bunun gibi sınıfları türetirken de bize o sınıfın hangi kurallar çerçevesinde oluşturulabileceğini, içerisindeki hangi özelliklerin ve işlevlerin hangi erişim türü veya değer tipinde olması gerektiğini, hangi işlev’in (fonksiyonun) ne tür değer döndürmesi gerektiğini bize bildiren bir sınıf türü vardır. Biz eğer bir sınıf oluşturur ve bunu soyutlarsak, yani asılda var olmayan soyut bir sınıf yapar ve buna özellikler ve işlevler tanımlarsak, esas sınıfımızı da bu sınıf üzerinden oluşturursak sınıf soyutlama (abstraction) yapmış oluyoruz.

  • Soyut bir sınıfta tanımlanan özellik ve işlevler private olamazlar.
  • Soyut bir sınıftan nesne türetilemez, soyut sınıflar nesne türetmek için değildir. Nesne türetilecek bir sınıf için referans oluşturmak amaçlıdır.
  • Soyut sınıflarda işlevler ile belli görevler yerine getirilmez. Sadece işlevler ve kuralları yazılır. İçini doldurarak gerçekten bir görevi yerine getirmesini sağlama işi soyut sınıfın değil, esas sınıfın işidir.
  • Soyut sınıfın içerisinde tanımlanan özellikler (değişkenler) asıl sınıfta tekrar tanımlanmaz, direkt kullanılırlar.

C# Örneği;

abstract class Tasit
{
    public string marka;
    public string model;
    protected int km;
    protected bool kontak;
    public abstract void kontakCevir(bool durum);
    public abstract void tasitSur();
    protected abstract void kmYaz(int m);
}

PHP Örneği;

abstract class Tasit
{ 
    abstract public $marka;
    abstract public $model;
    abstract protected $km;
    abstract protected $kontak;
    abstract public function kontakCevir((bool)$durum);
    abstract public function tasitSur();
    abstract protected function kmYaz((int)$m);
}

Bu kod parçası ile soyut bir “Taşıt” sınıfı oluşturduk ve 4 adet özellik, 3 adet işlev tanımladık.

Not: C#’ın bir kuralı olarak abstract class’tan türetilen bir işlev yazacaksak ovverride etiketini kullanırız. Yine C# syntax yapısına göre soyut sınıftaki değişkenlere ulaşmak için base ön tanımını kullanırız.

C# Örneği;

class Araba : Tasit
{
   public ovverride void kontakCevir(bool durum)
   {
       base.kontak = durum;
   }
   public override void tasitSur()
   {
       this.kmYaz(base.km+1);
   }
   protected override void kmYaz(int m)
   {
       base.km = m;
   }
}

PHP Örneği;

class Araba extends Tasit
{
   public function kontakCevir($durum)
   {
      $this->kontak = $durum;
   }
   public function tasitSur()
   {
     $this->kmYaz($this->km+1);
   }
   protected function kmYaz($m)
   {
     $this->km = m;
   }
}

Burada ise birazdan bahsedeceğimiz kalıtım (inheritance) özelliğini kullanarak soyut sınıfımızı baz alan “Araba” adında bir sınıf oluşturduk.
Soyut sınıfın bize sunduğu bilgiler doğrultusunda işlevlerimizi oluşturduk.
Gerçek sınıfta, soyut sınıftaki tipler aynen yazılır. Soyut sınıfın esas amacıda budur. Yani soyut sınıfta public olan bir kontakCevir işlevi yazıldıysa ve bu işlev bool tipinde bir durum parametresi alıyorsa geriye de void türünde değer döndürüyorsa; sizin gerçek sınıfınızda da aynen bu kurallara uymak zorundadır. Aksi halde derleme (compile) sırasında hata mesajı ile karşılaşırsınız.

Abstraction’a bu açıdan baktığımızda zaten özelliklerini biz belirliyorsak neden direk gerçek sınıfı oluşturmayıp, soyut sınıfla uğraşıyoruz? diyebilirsiniz. Ancak soyutlama işlemi gibi bir çok OOP işlemleri birden fazla kişinin, kompleks yapılar üzerinde çalıştığı sistemlerde kullanılmak üzere tasarlanmış, ortaya çıkmıştır. O yüzden bakış açımızı bu yöne çevirirsek, çok kompleks bir projede birden fazla kişi çalıştığı zaman türetilen sınıflarda uyumsuzluk doğabilir. Bool döndüren bir fonksiyondan bir geliştirici başka bir sonuç bekleyerek, başka bir sınıf türeterek String tipinde bir dönüş bekleyişi içine girerse en basitinden bu noktada bir uyumsuzluk doğduğunu görüyoruz. Bu hatanın kompleks bir yapının içindeki kritik veriler için yapıldığını düşünürsek sistemde mantıksa (logic) ve çalışma (runtime) hataları kaçınılmaz olur.


Kalıtım (Inheritance)

Kalıtım, anne ve babadan oğula, oğuldan toruna, torundan toruna şeklinde aktarılıp giden özellikler bütünüdür. Buna en güzel örnek insan yapısındaki DNA yani gerçek kalıtım malzemesidir. Bir anne ve babadan doğan çocuk, o anne ve babanın genetiğinden miras alır. Bu bazı özellikleri onlardan aldığı anlamına gelir.

Programlamada da kalıtımdan bahsederken aynı özellikten bahsederiz. Nesneleri var eden sınıflar daha önce Abstraction işleminde gördüğümüz gibi bir başka sınıfı kendisine “Mirasçı” seçebilir. Ondan bazı özelliklerini miras alarak var olur. İşte bu miras alarak var olma işlemine kalıtım (inheritance) denir.

Miras alan sınıf mirasçının özellik ve işlevlerini, kendi içerisinde kullandırmakla kalmayıp, bu sınıftan türetilen nesneler üzerinden de bunlara erişim sağlar.

C# Örneği;

class Matematik
{
    public int x,y;
    
    public int carpma()
    {
       return (this.x*this.y);
    }
    
    public double bolme()
    {
       return (this.x/this.y);
    }
   
    public int toplama()
    {
       return (this.x+this.y);
    }
    public int cikarma()
    {
       return (this.x-this.y);
    }
}
class Dikdortgen : Matematik
{
    public int alanHesapla(int a, int b)
    {
         base.x = a;
         base.y = b;
         return base.carpma();
    }
}
class Ucgen : Dikdortgen
{
     public double alani(int a, int b)
     {
         return base.bolme(base.alanHesapla(a,b), 2);
     }
}
Dikdortgen d = new Dikdortgen();
d.alanHesapla(3,4); //12
d.toplama(10,12); //22
Ucgen u = new Ucgen();
u.alani(3,4); //6
u.alanHesapla(3,5); //15

PHP Örneği;

class Matematik
{
   public $x;
   public $y;
   
   public function carpma()
   {
      return ($this->x*$this->y);
   }
   public function bolme()
   {
      return ($this->x/$this->y);
   }
   public function toplama()
   {
      return ($this->x+$this->y);
   }
   public function cikarma()
   {
      return ($this->x-$this->y);
   }
}
class Dikdortgen extends Matematik
{
   public function alanHesapla((int)$a, (int)$b)
   {
      $this->x = $a;
      $this->y = $b;
      return $this->carpma();
   }
}
class Ucgen extends Dikdortgen
{
   public function alani((int)$a, (int)$b)
   {
      return $this->bolme($this->alanHesapla($a,$b), 2);
   }
}
$dikdortgen = new Dikdortgen();
$dikdortgen->alanHesapla(3,5); //15
$dikdortgen->toplama(10,2); //12
$ucgen = new Ucgen();
$ucgen->alani(3,4); //6
$ucgen->alanHesapla(3,5); //15
$ucgen->cikarma(10,2); //8

Örneğimizi yakından inceleyecek olursak bir ana mirasçı olarak “Matematik” sınıfı oluşturduk. Bu sınıf temel matematik işlemlerini içeren bir sınıf olarak tanımlandı.
Daha sonra bu sınıfı “mirasçı” olarak gösterip “Dikdortgen” sınıfını oluşturduk. İçerisinde dikdörtgenin alanını bize döndüren bir işlev (fonksiyon) yazdık.
Dikdörtgen alanı hesaplanırken hepimizin bildiği gibi iki kenar uzunluğu çarpılır. Bu yüzden mirasçısı olan matematik sınıfından carpma işlevini çağırarak fonksiyona gelen iki değeri çarptık. Geriye ise sonucu döndürdük.
Daha sonra “Ucgen” sınıfını oluşturduk fakat bu kez mirasçı olarak “Dikdortgen” sınıfını gösterdik. Bu sınıf içerisinde de üçgen’in alanını dikdörtgen üzerinden hesaplayan bir işlev yazdık.

Burada dikkat edilmesi gereken en önemli nokta fonksiyonların isimleridir. Çünkü; “Ucgen” sınıfımız üzerinden oluşturulan bir nesnede hem Ucgen, hem “Dikdortgen” hemde “Matematik” sınıflarından fonksiyonlar çağırmamız mümkün hale geliyor. Bu yüzden mirasçılarda aynı isimde fonksiyonlar oluşturursak nesne tarafında bu fonksiyonları çağırırken programın hangi fonksiyona başvurduğunu ayırt etmemiz mümkün değildir. Sınıf içerisinde bu ayrımı “base” ön eki ile yapabiliriz ancak nesne üzerinde işlem yapacağımız zaman bu imkansız hale gelir.


Kapsülleme (Encapsulation)

Sınıf içerisindeki özellik (değişken) ve işlevlere (fonksiyon) erişim kurallarını belirleme işlemine yani diğer konularda bahsettiğimiz erişim tipi belirleme konusuna kapsülleme denir. Kapsülleme sadece erişim türünü belirlemekle ilgili değildir. Bu verilere erişimde ve bu verilerin nesne üzerinden düzenlenmesinde de özel kurallar oluşturabilmemizi sağlar. Mesela bir özellik değer alırken array formatında değer alsın fakat çağrıldığında JSON formatında çıktı versin diyebiliriz. Yani veriler üzerinde set (değer atama) ve get (çağırma) işlemleri sırasında farklı işlemler yapabilir, verileri veya veri formatlarını farklı değişikliklere uğratabiliriz. Tüm bu işlemlere kapsülleme (encapsulation) denir.

C# Örneği;

class Ornek
{
  private int a;
  private int b;
  public int B
  {
     get { return b; }
     set { b = value }
  }
}

PHP Örneği;

class Ornek
{
  private $a;
  private $b;
  
  public function __get( $var )
  {
     return $this->$var;
  }

  public function __set( $var, $value )
  {
     $this->$var = $value;
  }
}

Çok Biçimlilik (Polymorphism)

Polimorfizm bir sınıfın başka bir sınıfı baz alarak türetilmesi işlemidir. Abstraction işlemine benzese de arasında önemli farklar mevcuttur.

  1. Abstraction sınıfı üzerinden nesne türetilemez.
  2. Abstraction sınıfı üzerindeki işlevlerin içi boştur.

Çok biçimlilikte ise baz alınan sınıf gerçek bir sınıftır içerisinde işlevler mevcuttur ve bu sınıf üzerinden nesne türetilebilir haldedir.
Abstraction içerisindeki tüm kurallara uyulmalı, soyut sınıftan türetilen bir sınıfta soyut sınıftaki tüm değişken ve fonksiyonlar tanımlanmalı iken polimorfizm de bu farklı işlemektedir. Polimorfizm’de baz alınan sınıftaki tüm fonksiyonlar diğer sınıfta kullanılmayabilir. Burada amaç sınıfı türetirken bir başka sınıfı da çalışmaya dahil ederek tek nesne üzerinden iki sınıfında işlev ve özelliklerine ulaşmaktır. Fakat istenirse override yapılarak baz alınan sınıftaki bir fonksiyon tamamen yeniden, yeni kurallar ve görevler ile yazılabilir.

C# Örneği;

class Insan
{
   public string isim, soyisim;
   protected string kimlikno;
   protected string mesaj;
   public virtual void konus()
   {
      Console.WriteLine(mesaj); 
   }
   public virtual void adiniSoyle()
   {
      Console.WriteLine(base.isim+' '+base.soyisim);
   }
}
class birInsan : Insan
{
   base.isim    = "Murat";
   base.soyisim = "Bekler";
   base.kimlikno= "000000001";
   base.mesaj   = "Merhaba!";
  
   public override void konus()
   {
      Console.WriteLine(base.mesaj+' Benim ismim '+base.isim+' '+base.soyisim+');
   }
   public string kimlikNoGetir()
   {
      return base.kimlikno;
   }
}
class Turist : Insan
{
   base.isim    = "Jane";
   base.soyisim = "Doe";
   base.kimlikno= "000123";
   base.mesaj   = "Hello!";
}
birInsan Huseyin = new Insan();
Huseyin.konus(); // Merhaba! Benim ismim Murat BEKLER
Huseyin.kimlikNoGetir(); // 000000001
Huseyin.adiniSoyle(); // Murat BEKLER
Turist Jane = new Turist();
Jane.konus(); // Hello!
Jane.adiniSoyle(); // Jane Doe

Bir insan sınıfı oluşturduk bu sınıftan birInsan ve Turist isimlerinde iki sınıf daha türettik. Insan sınıfımızdaki konus fonksiyonunu override yaparak iki sınıfta da farklı işlevlerle kullandık. Bunun yanı sıra adiniSoyle fonksiyonuna dokunmadık ve onu da iki sınıfta da kullandık. Dilersek onu da override ile türetilen sınıflarda yeniden farklı bir şekilde çalışmaya zorlayabilirdik.

PHP Örneği;

class Insan
{
   public $isim;
   public $soyisim;
   protected $kimlikno;
   protected $mesaj;
 
   public function konus()
   {
      echo $this->mesaj; 
   }
   public function adiniSoyle()
   {
      echo $this->isim.' '.$this->soyisim;
   }
}
class birInsan extends Insan
{
 public function __construct()
 {
  
  $this->isim  = 'Murat';
  $this->soyisim = 'Bekler';
  $this->mesaj  = 'Merhaba!';
  $this->kimlikno = '0XXXXXXXXX';
 }
 
 public function konus()
    {
  echo $this->mesaj;
    }
 
 public function kimlikNoGetir()
    {
  echo $this->kimlikno;
    }
}
class Turist extends Insan
{
 public function __construct()
 {
 
  $this->isim  = 'Jane';
  $this->soyisim  = 'Doe';
  $this->mesaj = 'Hello!';
  $this->kimlikno = '2323232';
 }
}
$b = new birInsan();
$b->konus();          //Merhaba! Benim ismim Murat BEKLER
$b->adiniSoyle();    //Murat BEKLER
$b->kimlikNoGetir(); //0XXXXXXXXX
$t = new Turist();
$t->konus();          //Hello!
$t->adiniSoyle();    //Jane Doe