Kalıtım

Kodun kalıtım yoluyla yeniden kullanımının teşvik edilmesi NYP 'nin karakteristik özelliğidir. Temel sınıf olarak adlandırılan bir sınıftan yeni bir sınıf elde edilir. Türetilen sınıf, temel sınıfın üyelerini kullanır ama bunlar üzerinde şekillendirmeler ve ilaveler de yapabilir.

Birçok tip zaten var olan başka bir tipin versiyonudur. Bunların her biri için yeni bir kod yazmak çoğunlukla yorucudur. Ayrıca, yeni kod yeni hatalar anlamına gelir. Türetik sınıf temel sınıfın tarifini miras alır. Bu şekilde kodun yeniden geliştirilmesi ve sınanması gereksiz olur. Kalıtım ilişkileri hiyerarşiktir.

Hiyerarşi, elemanların tüm çeşitlilik ve karmaşıklığı ile kopyalanmasını sağlayan bir yöntemdir. Nesnelerin sınıflandırmasını sağlar. Örneğin, elementlerin periyodik tablosunda gazlar vardır. Bunlar tüm elementlerde kalıtımsal olan özellikleri taşırlar.

Asal gazlar ise bir sonraki önemli alt sınıfı oluşturur. Burada hiyerarşi, argon gibi bir asal gazın, bir gaz olması ve gazın da kendi çapında sistemin bir parçası olmasıdır. Böylece, asal gazın davranışının kolayca açıklanması sağlanır. Bunların atomlarının, protonları ve elektronları içerdiğini biliriz -ki bu diğer tüm elementler için de geçerlidir.

Diğer tüm gazlar gibi, oda sıcaklığında gaz halinde olduklarını biliriz. Asal gaz alt sınıfından hiç bir gazın diğer elementlerle kimyasal reaksiyona girmediğini biliriz; bu bütün asal gazların özelliğidir.

Geometrik şekillerin kalıtımına dair bir örneği göz önüne getirelim. Basit şekillerden (daire, üçgen, dikdörtgen, kare vb.) oluşan bir grubu tanımlamak için en iyi yol , her bir türetik şeklin atası olan bir temel sınıf (SVT) oluşturmaktır.

Şekli tarif eden en bilindik üyeleri içeren CShape isminde bir temel sınıf oluşturalım. Bu üyeler tüm şekillerde karakteristik olan özellikleri (şekil tipi ve tutturma koordinatları) tarif eder.

Örnek:

//--- Şekil temel sınıfı
class CShape
  {
protected:
   int       m_type;                   // Şekil tipi
   int       m_xpos;                   // X - merkez nokta koordinatı
   int       m_ypos;                   // Y - merkez nokta koordinatı
public:
             CShape(){m_type=0; m_xpos=0; m_ypos=0;} // yapıcı
   void      SetXPos(int x){m_xpos=x;} // X'i ayarla
   void      SetYPos(int y){m_ypos=y;} // Y'yi ayarla
  };

Daha sonra, temel sınıftan türetilen yeni sınıflar oluşturulur. Bunlara, her biri belli bir sınıfı tanımlayan gerekli alanlar eklenir. Daire şekli için, yarıçap değerini içeren bir üyenin eklenmesi gereklidir. Kare şekli ise kenar değeri ile nitelenir. Bu yüzden, CShape temel sınıfından kalıtım yoluyla türetilen alt sınıflar, şu şekilde bildirilirler:

//--- Türetik sınıf daire
class CCircle : public CShape        // İki nokta işaretinden sonra temel sınıfı tanımlarız
  {                                    // kalıtımın geldiği sınıf
private:
   int             m_radius;           // daire yarıçapı
 
public:
                   CCircle(){m_type=1;}// yapıcı, tip 1 
  };

Şekil sınıfının bildirimi Kare için de benzerdir:

//--- türetik sınıf Kare
class CSquare : public CShape        // İki nokta işaretinden sonra temel sınıfı tanımlarız
  {                                    // kalıtımın geldiği sınıf
private:
   int            m_square_side;       // kare kenarı
 
public:
                  CSquare(){m_type=2;} // yapıcı, tip 2 
  };

Nesne oluşturulurken ilk olarak temel sınıf yapıcısının, daha sonra ise türetik sınıfın yapıcısının çağrılacağı not edilmelidir. Nesne yok edilirken ise, önce türev sınıf yıkıcısı, ardından temel sınıf yıkıcısı çağrılır.

Bu şekilde, en genel üyeleri temel sınıfta bildirip, daha özel sınıfları belirleyen diğer üyeleri türetik sınıflara ekleyebiliriz. Kalıtım defalarca kullanılabilen güçlü kodların oluşturulmasını sağlar.

Halihazırda mevcut olan bir sınıftan, bir türetik sınıf oluşturulmasının sözdizimi şu şekildedir:

class sınıf_ismi : 
          (public | protected | privateopt  temel_sınıf_ismi
  {                                    
   sınıf üyelerinin bildirimi
  };

 

Türetik sınıfın önemli bir yönü, üyelerinin ve haleflerinin (kalıtımsal varisler) görünürlüğüdür. 'public', 'protected' ve 'private' erişim belirteçleri, kapsamı - yani temel sınıfın hangi üyelerinin, türetik sınıflar için mevcut olacağını - belirtmek için kullanılır. Türetik sınıfın başlığında iki nokta işaretinden sonra yer alan 'public' anahtar sözcüğü, CShape temel sınıfının korunan (protected) ve genele açık (public) üyelerinin, CCircle türetik sınıfının korunan ve genele açık üyeleri şeklinde miras alınması gerektiğini belirtir.

Temel sınıfın özel (private) üyeleri, türetik sınıf için kullanılabilir değildir. Genele açık kalıtım, türetik sınıfların (CCircle ve CSquare) aynı zamanda CShapes sınıfı oldukları anlamına da gelir. Şöyle ki, Kare (CSquare) bir şekildir (CShape) ama şekil kare olmak zorunda değildir.

Türetik sınıf, temel sınıfın bir modifikasyonudur ve temel sınıfın korunan ve genele açık üyelerini miras alır. Temel sınıfın yapıcıları ve yıkıcıları miras bırakılamaz. Temel sınıfın üyelerine ek olarak, yeni üyeler de türetik sınıfa eklenir.

Türetik sınıf, üye fonksiyonların temel sınıftan farklı uygulamalarını içerebilir. Bunun aşırı-yükleme ile herhangi bir alakası yoktur; çünkü aynı fonksiyon ismi farklı imzalarla kullanılabilir.

Korunan kalıtım durumunda, temel sınıfın genele açık ve korunan üyeleri, türetik sınıfın korunan üyeleri haline gelir. Özel kalıtım durumunda, temel sınıfın genele açık ve korunan üyeleri, türetik sınıfın özel (private) üyeleri haline gelir.

Korunan ve özel kalıtımlarda, "bir türetik sınıf nesnesi aynı zamanda bir temel sınıf nesnesidir" ilişkisi doğru değildir. Korunan ve özel kalıtım tipleri nadirdir ve her biri dikkatle kullanılmalıdır.

Kalıtımsal hiyerarşi ile türetik sınıftan temel sınıfın üyelerine gerçekleştirilen erişim şekillerinin, kalıtım tipinden (public, protected veya private) etkilenmeyeceği not edilmelidir. Tüm kalıtım türlerinde, sadece public ve protected erişim belirteçleri ile bildirilen temel sınıf üyeleri türetik sınıfın dışında kullanılabilir. Şu örneği göz önüne alalım:

#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Birkaç erişim tipine sahip sınıf örneği                          |
//+------------------------------------------------------------------+
class CBaseClass
  {
private:             //--- Özel üye, türetik sınıflar için mevcut değil
   int               m_member;
protected:           //--- Korunan yöntem temel sınıf ve türetik sınıflar için mevcut durumda
   int               Member(){return(m_member);}
public:              //--- Sınıf yapıcısı tüm sınıfların üyeleri için mevcut durumda
                     CBaseClass(){m_member=5;return;};
private:             //--- m_member değişkenine değer atamak için özel bir yöntem
   void              Member(int value) { m_member=value;};
 
  };
//+------------------------------------------------------------------+
//| Hatalarla türetik sınıf                                          |
//+------------------------------------------------------------------+
class CDerived: public CBaseClass // genele açık kalıtımın tanımı (ön tanımlıysa) dahil edilmeyebilir
  {
public:
   void Func() // türetik sınıfta, temel sınıf üyelerinin çağrılarını içeren bir fonksiyon tanımla
     {
      //--- temel sınıfın özel bir üyesini şekillendirme denemesi
      m_member=0;        // Hata; temel sınıfın özel üyesi mevcut değil
      Member(0);         // Hata; temel sınıfın özel yöntemi, türetik sınıflarda mevcut değil
      //--- Temel sınıf üyesinin okunması
      Print(m_member);   // Hata; temel sınıfın özel üyesi mevcut değil
      Print(Member());   // Hata yok; korunan yöntem, temel sınıfta ve türetik sınıflarda mevcut
     }
  };

Yukarıdaki örnekte, CBaseClass sadece genele açık (public) yönteme sahip – yapıcı. Yapıcılar bir sınıf nesnesi oluşturulduğunda otomatik olarak çağrılırlar. Bu yüzden, özel üye m_member ve korunan yöntemler Member() dışarıdan çağrılamazlar. Ama genele açık kalıtım durumunda, temel sınıfın Member() yöntemi türetik sınıflardan kullanılabilir olacaktır.

Korunan kalıtım durumunda ise, public ve protected belirteçlerine sahip olan tüm temel sınıf üyeleri korunur. Bu demektir ki; temel sınıfın genele açık veri üyelerine ve yöntemlerine dışarıdan erişim serbestken, korunan kalıtım durumunda sadece türetik sınıftan ve onun türevlerinden erişim yapılabilir.

//+------------------------------------------------------------------+
//| Birkaç erişim tipine sahip sınıf örneği                          |
//+------------------------------------------------------------------+
class CBaseMathClass
  {
private:             //--- Özel üye, türetik sınıflar için mevcut değil
   double            m_Pi;
public:              //--- m_Pi için bir değerin alınıp ayarlanması
   void              SetPI(double v){m_Pi=v;return;};
   double            GetPI(){return m_Pi;};
public:              // Sınıf yapıcısı tüm üyelerce kullanılabilir
                     CBaseMathClass() {SetPI(3.14);  PrintFormat("%s",__FUNCTION__);};
  };
//+------------------------------------------------------------------+
//| m_Pi'nin değiştirilemeyeceği bir türetik sınıf                   |
//+------------------------------------------------------------------+
class CProtectedChildClass: protected CBaseMathClass // Korunan kalıtım
  {
private:
   double            m_radius;
public:              //--- Türetik sınıftaki genele açık yöntemler
   void              SetRadius(double r){m_radius=r; return;};
   double            GetCircleLength(){return GetPI()*m_radius;};
  };
//+------------------------------------------------------------------+
//| Script starting function                                         |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Türetik sınıf oluşturulurken, temel sınıfın yapıcısı otomatik olarak çağrılır
   CProtectedChildClass pt;
//--- Yarı çapı belirle
   pt.SetRadius(10);
   PrintFormat("Length=%G",pt.GetCircleLength());
//--- Eğer dizgi aşağıdaki gibi yorumlanırsa, SetPi() korunduğu için derleme aşamasında bir hata alırız
// pt.SetPI(3); 
 
//--- Şimdi temel sınıfın bir değişkenini bildirelim ve Pi sabitini 10 olarak ayarlayalım
   CBaseMathClass bc;
   bc.SetPI(10);
//--- Sonuç şöyle olur
   PrintFormat("bc.GetPI()=%G",bc.GetPI());
  }

Örneğe göre, CBaseMathClass temel sınıfındaki SetPI() ve GetPi() yöntemleri açık erişime sahiptir ve programın herhangi bir yerinden çağrılabilirler. Ama aynı zamanda türetik CProtectedChildClass için, bu yöntemler sadece CProtectedChildClass sınıfının veya onun türetik sınıflarının yöntemlerinden çağrılabilir.

Özel kalıtım durumunda, temel sınıfın genele açıkve korunan erişime sahip tüm üyeleri özel hale gelir; daha sonraki kalıtımlarda çağrılmaları imkansız olur.

MQL5 çoklu kalıtım içermez.

Ayrıca Bakınız

Yapılar ve Sınıflar