top of page

Java Ders Notlarım – 5

Güncelleme tarihi: 3 Tem 2023

Bu yazımda sizlere dilim döndüğünce Java dilindeki Inheritance(Kalıtım) konusunu, overrriding, Encapsulation kavramlarını, this, super, final anahtar kelimelerini ve equals methodunun anlatacağım. Keyifli okumalar, iyi kodlamalar 😋

Java daki veri tiplerini primitive(ilkel) ve object veri tipi olarak ikiye ayırabiliriz. Ama her zaman bu veri tiplerini kullanmayabiliriz. Mesela bazen bu veri tipleriyle yeni bir özel class(sınıf) tanımlayabiliriz.

İşte bu oluşturduğumuz yeni özel sınıfı nasıl ki object sınıfını temel alarak oluşturduysak, aynı şekilde kendi özel sınıfımızdan da tekrardan yeni bir sınıf türetebiliriz. Mesela Kendimize özgü bir sınıf tanımlayalım.

public class Tasit
{
     String TasitAdi;
}
 

Kendisinden yeni bir sınıf türetilen sınıfa base class denir.Bazen bu base class yerine parent class da karşınıza çıkabilir.

Türetilen yeni sınıfa da drive class veya sub class denir. Bir de child class var o da drive class ile aynı manadadır. Türetilen bu sınıf otomatik olarak kendisinin türetildiği sınıfın tüm özelliklerini kalıtım yoluyla alır. Bu özellikler methodlar,değişkenlerdir. Hatta bu özelliklerin tümüne birden Member yani türkçe meali üye de denir.

Yani bizim bu Tasit adli sınıfımızdan yeni bir sınıf oluşturduğumuzda, bu Tasit adlı sınıfa base class veya super class denir. Peki bu sınıftan türeteceğimiz yeni sınıfı nasıl türeceğiz? Cevap extends anahtarında gizli 😀. Gırgırı bırakıp sınıfımızı nasıl oluşturacağımıza dair bir örnek vereyim.

public class Araba extends Tasit
{

}
 

Bu şekilde yazarak artık Tasit adlı sınıftaki bütün özelliklere sahip olan yeni bir class türetmiş olduk. Bunun adına da Araba dedik. Bu arada türettiğimiz yeni sınıfta normalde Tasit sınıfındaki üyeleri yazmanıza gerek yoktur. Bu üyeler otomatik olarak o sınıfa java tarafından tanımlanıyor zaten. Örneğin Tasit sınıfının içerisindeki TasitAdi değişkenine aşağıdaki gibi erişebiliyoruz:

public static void main(String[] args)
{
	Tasit tasit = new Tasit();
	//tasit.TasitAdi
	
	//ekrana bu değişkenin değerini yazdırmak istersek
	System.out.println(tasit.TasitAdi);
}
 

Peki yeni oluşturduğumuz classta TasitAdi gibi bir ibare yazmadığımız halde Araba sınıfından TasitAdi değişkenine erişebiliyor muyuz? Tabiki de evet. İşte bu olaya kalıtım diyoruz. Şu şekilde göstereyim:

public static void main(String[] args)
{
	Araba araba = new Araba();
	//ekrana bu değişkenin değerini yazdırmak istersek
	System.out.println(araba.TasitAdi);
}
 

Diyelimki biz Tasit sınıfını şu şekilde tanımladık:

public class Tasit
{
        String TasitAdi;
	void EkranaYazdir()
	{
		System.out.println("Tasit Sınıfının methodu calisti!");
	}
}
 

ve Araba sınıfı da şu şekilde olsun:

public class Araba extends Tasit
{

}
 

Bu durumda ben Aşağıdaki gibi bir kodu çalıştırırsam:

public static void main(String[] args)
{
	Tasit tasit = new Tasit();
	tasit.EkranaYazdir();
}
 

Alacağımız çıktı şu şekilde olur:

Tasit Sınıfının methodu calisti! 

Aynı şekilde ben Araba sınıfından da yeni tanımladığım EkranaYazdir methodunu çağırabilirim. Yani Aşağıdaki gibi bir kodu çalıştırırsam:

public static void main(String[] args)
{
	Araba araba = new Araba();
	araba.EkranaYazdir();
}
 

Alacağımız çıktı yine şu şekilde olurdu:

Tasit Sınıfının methodu calisti! 

Nedir bu Overriding Kavramı?

Overriding dediğimiz şey ingilizceden “ağır basma” şeklinde çevirebiliriz Peki bugun java programlamadaki anlamı ne? diye soracak olursanız. Şöyle açıklayayım :

Yine aşağıdaki gibi tanımlanmış iki tane sınıfımız olsun:

public class Tasit
{
	String TasitAdi;
	
	void EkranaYazdir()
	{
		System.out.println("Tasit Sınıfının methodu calisti!");
	}
}

public class Araba extends Tasit
{

}
 

Biz şimdi Araba sınıfını Tasit sınıfından kalıtım alarak oluşturduğumuz için EkranaYazdir methodunu ekstra bir şekilde tanımlamadan kullanabiliyorduk. Ama diyelim ki siz Araba sınıfın kullanırken EkranaYazdir methodunu çağırdığınız zaman Tasit sınıfındaki method değilde benim istediğim method çalışsın. O zaman yapmanız gereken şey aşağıdaki gibi Araba sınıfın içerisine EkranaYazdir methodunu tekrar yazmaktır. Yani sınıflarımızı aşağıdaki gibi tanımlarsak:

public class Tasit
{
	String TasitAdi;
	
	void EkranaYazdir()
	{
		System.out.println("Tasit Sınıfının methodu calisti!");
	}
}

public class Araba extends Tasit
{
	void EkranaYazdir()
	{
		System.out.println("Araba Sınıfının methodu calisti!");
	}
}
 

ve Aşağıdaki Kodu çalıştırırsak:

public static void main(String[] args)
{
	Araba araba = new Araba();
	araba.EkranaYazdir();
}
 

Alacağımız Çıktı şu şekilde olurdu:

Araba Sınıfının methodu calisti! 

Yani kısaca bu overriding dediğimiz şey, Türetilen bir sınıfın (Araba) içerisine türetildiği sınıftaki(Tasit) methodun(EkranaYazdir) aynı şekilde tanımlamak (ve o method içerisinde farklı işler yaptırmaktır) diyebiliriz.

covariant return type Nedir?

Overriding işleminin olması için türetilen sınıftaki tanımlanan methodun türetildiği sınıftaki method ile aynı isimde olması ve aynı dönüş tipine (örn void) sahip olması gerekiyor. Ama java 5.0 dan sonra eklenen kolaylık sayesinde isim aynı kalmak şartıyla dönüş tipi farklı olan fonksiyonlar tanımlayabilirsiniz. İşte bu olaya covariant return type deniyor. Burda dikkat etmemiz gereken nokta geri dönüş tipi object veri tiplerinde ve object veri tipinden türetilmiş sınıflarda geçerlidir.

Örnek olarak:

public class Tasit
{
	String TasitAdi;
	
	Tasit BosSinifOlustur()
	{
		return new Tasit();
	}
}

public class Araba extends Tasit
{
	void EkranaYazdir()
	{
		System.out.println("Araba Sınıfının methodu calisti!");
	}
	
	Araba BosSinifOlustur()
	{
		return new Araba();
	}
}

 

Yani yukarıdaki tanımlama geçerlidir.

Ayrıca overriding yaptığımız fonksiyonun erişim düzeyi private ise bunu overriding ile public veya protected yapabiliyoruz ama tersi mümkün değil

final anahtar kelimesi

Bir sınıf veya method tanımlarken sınıfın veya methodun isminden önce final kelimesini yazarsanız bu sınıf tekrar türetilemez olur veya bu method overriding yapılamaz. Örneğin:

public final class Tasit
{
	public final String Isim = "";
	public int Model;
	
	
public final void Yazdir()
	{
		System.out.println(Isim);
	}
}
 

super constructor nedir?

Türetilmiş bir sınıftan bir üst sınıfın constructorunu çağırmak için kullandığımız ifadedir. Örneğin:

public class Araba extends Tasit
{
	public Araba()
	{
		// bir üst sınıfa yani Tasit sınıfının constructor'una aşağıdaki gibi ulaşıyoruz
		super(/* eğer constructor parametre alıyorsa buraya yazın*/);

		//veya parametreli ise
		super(argument1, argument2);
		
	}
}
 

this constructor nedir?

Türetilmiş bir sınıfta birden fazla constructor var ise bu sınıftaki bir constructordan yine aynı sıfıntaki diğer constructor’ı çağırmak için kullandığımız ifadedir. Örneğin:

public class Araba extends Tasit
{
	public Araba()
	{
		this(argument1, argument2);
	}
	public Araba(type1 param1, type2 param2)
	{
		. . .
	}
}
 

Türetilmiş bir sınıfın tipi kendisidir. Örneğin Tasit sınıfının tipi Tasit‘tir ve Araba sınıfının tipi Araba‘dır.

Encapsulation olayı nedir?

Bu ifadeyi şöyle düşünebilirsiniz. Şimdi bizim bir tane Tasit sınıfımız ve bir tane de Araba sınıfımız vardı. Bu sınıfları şöyle tanımlayalım:

public class Tasit
{
	private String TasitAdi;
	
	private EkranaYazdir()
	{
		System.out.println("Tasit Sınıfının methodu calisti!");
	}
}
public class Araba extends Tasit
{

}
 

Bu tanımlamalardan yolaca çıkarak aşağıdaki gibi bir kodu çalıştırmak istersek:

public static void main(String[] args)
{
	Araba araba = new Araba();
	System.out.println(araba.TasitAdi);
}
 

araba.TasitAdi kısmında hata alırsınız. Eclipse bu hata not visible(yani görünür değil) olarak çıkıyor. Yani anlayacağınız Erişim düzeyleri dediğimiz bir muhabbet var. Bundan dolayı parent class içerisinde tanımladığınız private bir üyeye child class üzerinden erişemezsiniz. Çünkü parent class içerisinde o üyeyi private olarak tanımladığınızda o üyeyi kapsüllemişsiniz gibi düşünebilirsiniz. Bunun çözümü yani o üyeye child classtan erişmek isterseniz private yerine protected veya public yazmanız işinizi görecektir.

Bu kapsülleme olayı değişkenlerde olduğu gibi methodlarda da aynen geçerlidir.

Ayrıca static olarak tanımlanan değişkenler de aynı şekilde child class’a otomatik olarak aktarılacaktır.

Child sınıftan Parent sınıftaki üyelere erişmek için super anahtar kelimesi kullanılır. Yani aşağıdaki gibi tanımlanmış iki sınıfımız olsun:

public class Tasit
{
	public String toString()
	{
		return "Üst Sınıf";
	}
}

public class Araba extends Tasit
{
	public String toString()
	{
		return (super.toString() + " $ " + "alt sınıf");
	}
}
 

Aşağıdaki gibi kodu çalıştırırsak:

public static void main(String[] args)
{
	Araba araba = new Araba();
	System.out.println(araba.toString());
}
 

Çıktısı şöyle olacaktır:

Üst Sınıf $ alt sınıf 

Benzer bir şekilde üst sınıfında üst sınıfına erişmek istediğiniz zaman aşağıdaki gibi bir kod kullanmak isterseniz:

super.super.toString();
 

Bu kullanım biçimi hatalı bir kullanımdır. izin verilmez. Mesela Eclipse sytnax hatası ile karşılaşırsınız.

Java da tanımlı olan tüm sınıflar Object sınıfından türetilmiştir.Object sınıfında ise equals ve toString methodları bulunmaktadır siz yeni bir sınıf oluşturduğunuzda bu methodlar otomatik tanımlı olarak gelecektir.

equals methodunun doğru kullanım şekli

Normalde iki ilkel değişkeni (örn int) == operatörüyle karşılaştırdığınız zaman bu değişkenlerin değerlerini karşılaştırmış olursunuz ama. Object sınıfından oluşturduğumuz herhangi bir klası aynı türden başka bir class ile karşılaştırmak istersen == operatörünü kullanmak isteyebilirsiniz ama böyle yaptığınızda arkaplanda olan şey iki sınıfın bellekteki adresini karşılaştırmaktır. Eğer bunun yerine iki classını doğru bir biçimde içerisindeki değişkenlerin değerlerini karşılaştırmak istediğimiz zaman equals methodu imdadımıza yetişiyor. Bu method içerisinde sınıfın üyelerini tek tek == operatörüyle karşılaştırarak o sınıfın paramtre olarak girilen sınıfa değer olarak eşit olup olmadığını öğrenebiliriz.

Örnek için bir tane sınıf tanımlayalım:

public class Tasit
{
	public String Isim;
	public int Model;
	
	
	public boolean equals(Tasit arg)
	{
		return (Isim.equals(arg.Isim) && Model == arg.Model);
	}
}
 

Ve tanımladığımız bu sınıf ile yeni sınıflar oluşturarak bu sınıfların değerlerini karşılaştırmak istersek:

public static void main(String[] args)
{
	Tasit tasit1 = new Tasit();
	tasit1.Isim = "Araba";
	tasit1.Model = 2020;
	
	Tasit tasit2 = new Tasit();
	tasit2.Isim = "Araba";
	tasit2.Model = 2020;
	
	if (tasit1.equals(tasit2))
	{
		System.out.println("Taşıtlar aynıdır.");
	}
	else
	{
		System.out.println("Taşıtlar aynı değil!");
	}
}
 

Alacağımız çıktı şu şekildedir:

Taşıtlar aynıdır. 

Veee bir notumuzun daha onuna gelmiş bulunmaktayız. Buraya kadar bıkmadan sabırla geldiysen sizden iyi bir programcı olur diyor ve sizi tebrik ediyorum 😅. Yeni notlarda, yeni paylaşımlarda görüşmek dileğiyle…

İyi Kodlamalar 💻🎉

Comments


bottom of page