Inheritance (miras, kalıtım) ve türleri nedir?

Inheritance (miras, kalıtım) ve türleri nedir?

Bu yazıda, inheritance kavramını detaylı olarak inceleyeceğiz.
Elif Koç06 Ara 2022

Miras (inheritance), mevcut bir sınıfa dayalı olarak yeni bir sınıf tanımlamayı sağlayan nesneye yönelik programlamanın temel özelliklerinden biridir. Yazıda sıklıkla karşılaşacağınız terimlerin tanımları ile başlayalım..

 

Terminoloji:

  • Sınıf (class): Ortak özelliklere sahip bir grup nesnedir. Nesnelerin oluşturulduğu bir şablon veya plandır.
  • Alt sınıf (subclass/childclass): Diğer bir sınıfı miras alan sınıftır. Ayrıca türetilmiş sınıf, genişletilmiş sınıf olarak da adlandırılır.
  • Süper sınıf/üst sınıf (superclass/parentclass): Bir alt sınıfın özellikleri devraldığı sınıftır. Ayrıca temel sınıf veya ana sınıf olarak da adlandırılır.


 

Inheritance’ta ana fikir, yeni alanlar ve yeni yöntemler ekleyerek veya mevcut yöntemleri yeniden tanımlayarak alt bir sınıf türetmek için mevcut bir sınıfı iyileştirmektir.  Alt sınıflar, mevcut sınıfın tüm alanlarını ve yöntemlerini devraldığı için yeniden kullanılmasını sağlar. Orijinal sınıfa üst sınıf, üst sınıfa dayalı sınıfa ise alt sınıf denir. Her sınıf, Java’daki Object sınıfından dolaylı olarak (implicitly) miras alır. Her sınıf bir nesnedir. Object sınıfının içinde alan yoktur, ancak equals ve toString gibi yöntemler vardır. Tüm sınıflar, hiyerarşinin en üstünde Object olacak şekilde bir hiyerarşide (ağaç) düzenlenir.


 

Java’da kullanılan inheritance (miras) anahtar sözcüklerini (keywords) inceleyelim.

Extends: Başka bir sınıfı extend eden (genişleten) bir sınıf, üst sınıfın (superclass) tüm alanlarını ve yöntemlerini (construct’lar dışında) devralan bir alt sınıftır (subclass). Alt sınıfın (subclass) public ve protected olan tüm alanlara doğrudan erişimi vardır. Alt sınıf, yeni uygulamalarla (aynı imzayı kullanarak) devralınan yöntemlerin tanımlarını geçersiz kılabilir ve super anahtar sözcüğünü kullanarak geçersiz kılınan yöntemlere erişebilir.


 

Aşağıda bir superclass örneği görülebilmektedir:

 

Başka bir üst sınıf belirtilmemişse, bir üst sınıf otomatik olarak Object sınıfından miras alır.

 

Aşağıda bir subclass örneği görülebilmektedir:

 

Alt sınıfın; alt sınıfı üst sınıftan ayıran alanları ve metodları tanımlaması gerekir. Örneğin, SavingsAccount yani alt sınıf, balance alanını ve metodları BankAccount sınıfından devralır. Constructor devralınmaz. 

 

Peki neden Java’da constructor inherit edilemez? 

Constructor’lar sınıf adı ile aynı ada sahiptir. Bu nedenle, constructor’lar alt sınıfta miras alınmışsa, alt sınıf; üst sınıfın adına sahip constructor’ı içerecek. Bu durumda constructor’ın sınıf adıyla aynı ada sahip olması kuralı çiğnenecektir. Güvenlik açısından da bakılacak olursa constructor’ların inherit edilebilmesi halinde, encapsulation işlemi başarısız olurdu. Çünkü bir üst sınıfın constructor’ını kullanarak bir sınıfın özel üyelerine erişebiliriz.


 

Subclass ve inheritance ilişkisi

Alt sınıf üst sınıftan miras aldığında temelde iki işlemi yürütebilir:

  • Ata sınıfa ait tüm alanları miras alabilir.
  • Alt sınıf kendisine özgü ek alanlar tanımlayabilir. Yani, alt sınıfın nesneleri, üst sınıfın nesnelerinden daha fazla veri toplayabilir. Alt sınıf kendine özgü ek alanlar tanımlarken; devralınan yöntemleri geçersiz kılabilir (overriding) veya devralınan yöntemleri aşırı yükleyerek (overloading) yeni yöntemler tanıtabilir.


 

Constructor ve superclass ilişkisi

Subclass’ın kendine ait constructor’ı ve kendine ait private değişkenleri olabilir. Alt sınıfın constructor’ları yalnızca alt sınıfın değişkenlerini initialize edebilir. Bu sebeple, alt sınıfa ait bir değişken initialize edildiğinde, initialize edilen değişken otomatik olarak üst sınıfa ait constructor’lardan birini (default veya parametreleri constructolar) yürütmelidir.

Bir üst sınıfın yapıcısını çağırmak için super anahtar sözcüğü kullanılır.


 

Aşağıdaki görselde bulunan örnekte subclass’ın constructor’ı içerisindeki super() methodu, superclass’a ait constructor’ı çağırır.


 

Subclass içerisinde yeni metodlar tanımlanabilir:

 

Super class’ta bulunan getBalance() methodu aracılığıyla balance değişkenini elde ederiz. 


 

Alan ve metot görünürlüğü

Sınıflar ve sınıflarla ilişkili kısımlar görünürlük değiştiricilerine (visibility modifiers) sahiptir. Burada karşımıza üç kavram çıkar: Public, protected ve private.

Public: Herkes tarafından erişilebilir.

Protected: Paket içerisinden, sınıf içerisinden, subclass içerisinden erişilebilir.

Private: Sadece sınıf içerisinden erişebilir.


 

Java’da paket (package), ilgili sınıfları gruplamak için kullanılır. Bunu bir dosya dizinindeki bir klasör olarak düşünebilirsiniz. Ad çakışmalarını önlemek ve daha iyi korunabilir bir kod yazmak için paketler kullanılır.


 

Bir alt sınıf, protected bir üst sınıftaki alana erişebilir:


 

Yukarıdaki görselde BankAccount sınıfının üst sınıf, SavingsAccount sınıfının alt sınıf olduğunu hatırlayalım. SavingsAccount sınıfındaki addInterest metodundaki işlemlerde balance değişkeni kullanılıyor. BankAccount sınıfına ait protected balance değişkenine ulaşabiliyoruz.


 

Overriding ve inheritance

Bir yöntemi geçersiz kılmak (overriding), devralınan (inherited) bir yöntemi yeniden tanımlar. Miras alınan bir yöntem, alt sınıfın ihtiyaç duyduğu şeyi yapmazsa, alt sınıf onu yeniden tanımlayabilir. Bir yöntem, üst sınıfın tanımıyla aynı imzaya (metodların adı, parametreleri) ve dönüş türüne sahipse, devralınan yöntemi geçersiz kılar.


 

Aşağıdaki örnekte override edilen üst sınıfın metodunu çağırmak için super kullanılması görülebilmektedir. 1000 birim para üzerindeki para çekme işlemleri için 10 birimlik bir ücret çıkarır. Withdraw fonksiyonunu geçersiz kılınmasını ve uygun olan bir fonksiyon yazılmasını gösterir.

 

Object sınıfından miras alınan metodlar override edilmelidir. Object sınıfından miras alınan metodlar belirli alt sınıflar için düzgün çalışmaz, bu sebeple bu metotların geçersiz kılınması gerekir (override).


 

Is-A ilişkisi

Java’da kalıtım bir is-a ilişkisidir. Yani, kalıtımı yalnızca iki sınıf arasında bir is-a ilişkisi varsa kullanabiliriz. Örneğin; 

  • Portakal bir meyvedir.
  • Araba bir araçtır.
  • Estetik cerrahı bir doktordur.
  • Köpek bir hayvandır.

Burada araba araçtan, portakal meyveden miras alabilir.


 

Neden inheritance kullanıyoruz?

Inheritance kullanımı kodun yeniden kullanılabilirliğini (reusability) sağlar. Üst sınıfta bulunan kod, doğrudan alt sınıf tarafından kullanılabilir. Metot overriding, çalışma zamanı polimorfizmi(run time polymorphism) olarak da bilinir. Bu sebeple, Java’da kalıtım yardımıyla, polimorfizm elde edebiliriz.


 

Inheritance türleri

Beş tür kalıtım bulunmaktadır: Single inheritance, multilevel inheritance, hierarchical inheritance,  multiple inheritance, hybrid inheritance.

  • Single miras yapısında tek bir alt sınıf, tek bir üst sınıftan uzanır.
  • Multilevel miras yapısında bir alt sınıf, bir üst sınıftan genişler ve daha sonra aynı alt sınıf başka bir sınıf için üst sınıf görevi görür.
  • Hierarchical miras yapısında birden çok alt sınıf, tek bir üst sınıftan uzanır.
  • Multiple miras yapısında tek bir alt sınıf birden çok üst sınıftan uzanır. 
  • Hybrid miras yapısında iki veya daha fazla kalıtım türünün birleşimidir.

 


 

Bu yazımızda, inheritance’ın ne amaçla kullanıldığını ve türlerini inceleyip, superclass-subclass ilişkisine değinerek inheritance’ın nesneye yönelik programlama için önemini vurguladık. Abstract ve interface ile ilgili yazımıza da göz atmayı unutmayın.
 

Kaynaklar

İlginizi Çekebilir

Abstract vs interface

Elif Koç
Miuul topluluğunun bir parçası ol!

Abone ol butonuna tıklayarak Miuul'dan pazarlama ve haber içerikleri almayı onaylıyorum.