Yazan : Şadi Evren ŞEKER
Bu yazının amacı, JAVA programlama dilinde bir sınıfın, birden fazla sınıftan nasıl miras aldığını anlatmaktır. Temel olarak JAVA dilinde doğrudan çoklu kalıtım (multiple inheritance) bulunmaz. Yani aşağıdaki gibi bir kod hatalıdır:
public class bilgisayar_mühendisliğ_öğrencisi extends sayısal_öğrenci, üniversite_öğrencisi{
}
Yukarıdaki tanıma göre bir bilgisayar mühendisliği öğrencisi hem üniversite öğrencisidir hem de sayısal bölüm öğrencisidir. Ancak JAVA, yukarıdaki bu tanıma izin vermez ve extends kelimesinden sonra sadece tek bir sınıf ismi yazılmasına izin verir.
Buna rağmen, JAVA programlama dilinde arayüz kullanarak (interface) bir sınıfın birden fazla sınıftan miras almasını sağlayabiliriz.
Çoklu mirasa geçmeden önce tek bir sınıfı, arayüz kullanarak nasıl miras aldığımızı görelim ardından birden fazla sınıf için bu yöntemi geliştirelim.
interface sayısal_öğrencisi_olma_şartı{
public void analitik_düşünmek();
}
Yukarıda bir sayısal öğrencisi olma şartı arayüzü tanımlanmıştır. Bu arayüz, herhangi bir sınıf tarafından uygulanırsa (implements) bu sınıfın analitik_düşünmek şeklinde bir fonksiyonu bulunması gerekir.
Şimdi bir bilgisayar mühendisliği öğrencisinin bu şartı sağladığını JAVA dilinde modelleyelim:
Public class bilgisayar_mühendisliği_öğrencisi implements sayısal_öğrencisi_olma_şartı{
public void analitik_düşünmek(){
// fonksiyon içeriği…
}
}
Yukarıda kodda görüldüğü üzere, uygulama şartı olarak (implements) arayüzde bulunan fonksiyonun içeriği yazılmıştır. Bu kodlamadan sonra artık bilgisayar mühendisliği öğrencisinin, sayısal öğrencisi olma şartını sağladığını söyleyebiliriz.
Şimdi bilgisayar mühendisliğindeki öğrencileri sayısal öğrencisi olarak tanıtabiliriz:
public class sayısal_öğrencisi {
double ortalaması;
public sayisal_öğrencisi( sayısal_öğrencisi_olma_şartı s){
s.analitik_düşünmek();
}
}
public class bilgisayar_mühendisliği_öğrencisi implements sayısal_öğrencisi_olma_şartı{
public void analitik_düşünmek(){
System.out.println(“düşünüyorum….”);
}
}
public class test{
public static void main(String args[]){
sayısal_öğrencisi ali = new sayısal_öğrencisi( new bilgisayar_mühendisliği_öğrencisi());
}
}
Yukarıdaki kod sonucunda ekranda, “düşünüyorum….” yazısı belirir. Bunun anlamı, ali isimli sayısal öğrencisinin, düşünmek isminde bir fonksiyonu olmasıdır.
Yazının başında da belirtildiği gibi JAVA doğrudan bir kalıtım ilişkisini desteklemez. Ancak yukarıdaki şekilde sınıflar arasında bir arayüz tanımlayarak bu iki sınıf arasında kalıtım ilişkisi kurulabilir.
Yukarıdaki kodda, yapılan eylem iki farklı yanlış anlaşılmaya açıktır. Genelde sık yapılan bu hataları aşağıda anlatmaya çalışalım.
1. Kalıtım değildir.
Yukarıdaki kod modeli, tam olarak kalıtım değildir. Sadece fonksiyonlar üzerinde tanımlıdır. Örneğin arayüzler (interface) üzerinde değişken tanımlanamaz.
2. HASA ve ISA arasındaki fark.
HASA ilişki modeli ile bir nesnenin diğer bir nesneyi içermesi, ISA ilişki modelinden farklıdır.
Bu durumu aşağıdaki şekil üzerinden açıklamaya çalışalım. Örneğin aralarında ISA ilişkisi bulunan iki sınıfı ele alalım:
Bu çizimi bir küme modeli ile modellemek istersek aşağıdaki şekilde bir sonuç çıkar:
Yukarıdaki model, nesne varlığı açısından kurulmuştur. Bu modele göre, insan, öğrenci’nin bir alt sınıfıdır. Yani öğrenci, insanda olan bütün özellikleri ve eylemleri kapsar ilave olarak kendisine özgü bazı özellikleri de bulunabilir. ( bu modelleme aslında çok sağlıklı değildir çünkü genelde kavram-varlığı açısından karmaşaya sebep olur. Modele kavram-varlığı açısından bakılırsa aslında öğrenci, insanın bir alt kümesidir ve insan kümesinde farklı varlıklar da vardır (örneğin öğrenci olmayan diğer insanlar) ancak yukarıdaki model tekrar ediyorum nesne-varlığı açısından çizilmiştir).
Yukarıdaki modeli elde etmenin birinci yolu miras ilişkisi kurmaktır (kalıtım inheritance) diğer yolu ise HASA ilişkisi tanımlamaktır.
public class öğrenci extends insan{
}
Şeklindeki bir tanım, insan sınıfındaki bütün tanımları otomatik olarak öğrenci sınıfına taşıyacak ve ardından yukarıda çizilen küme modelini gerçekleyecektir.
public class öğrenci{
insan a;
}
Ancak bu gerçekleme bir kalıtım ilişkisi olarak kabul edilemez. Bu gerçeklemede aslında iki farklı varlık vardır ve bu varlıklar arasında var oluştan kaynaklanan bir fark yoktur.
public class test{
public static void main(String args[]){
insan ali = new insan();
öğrenci veli = new öğrenci();
veli.a= ali;
}
Yukarıdaki bu model sonucunda, ali, velinin bir alt kümesi halini alır ancak buradaki ali’nin varlığı ile veli’nin varlığı arasında bağlayıcılık yoktur. Örneğin veli nesnesi (object) yok edilmesi sonucunda ali yaşamına devam edebilir. Bu tip ilişkilere münasebet (aggregation) ismi verilmektedir ve yukarıdaki yazıda anlatılan arayüz marifetiyle kalıtımdan tamamen farklı bir yapıdadır.
hocam java da kalıtım içinde constructorlar hangi sıraya göre çalışır yani süperi kullanmasakda en üst sınıfdan altsınıfa doğrumudur , alt sınıftan tek int değer alan bir constructor var fakat altında süper kullanılmamış yine üst sınıfın constructırı mı çalışır çalışırsa üst sınıfın hangi constructırı çalışır tek değer parametre alan mı boş constructor mı,teşekkürler
çağırıldığı sıraya göre çalışırlar. Yani şayet bir sınıftan nesne tanımlıyorsanız ve bu sınıfın bir üst sınıfı varsa (miras aldığı), özel birşey yapmadığınız sürece, tanımlama yaptığınız sınıftaki constructor çalışır:
Yukarıdaki kod için aşağıdaki gibi bir nesne tanımlama yapalım:
Buna göre sadece deneme 2 yazısı ekranda belirir ve x sınıfından herhangi bir işlem gerçekleşmez çünkü tanımlanan nesne y sınıfından tanımlanmıştır.
Ancak yukarıdaki kodu aşağıdaki şekilde değiştirebiliriz:
Bu durumda aynı şekilde y sınıfından bir nesne tanımlanırsa, önce x sınıfındaki constructor, ardından da y sınıfındaki constructor çalışacaktır.
class B {
int xB=10;
B(){
metodB();
System.out.println(“B nin constr. calisti”);}
void metodB(){
System.out.println(“metodB:”+xB); }
}
class C extends B {
int xC=1;
int xB=4;
C(){
System.out.println(“C nin constr. calisti”);
}
void metodC(){
System.out.println(“metodC”);
}
@Override
void metodB(){
super.metodB();
System.out.println(“C sınıfındaki metodB:”+super.xB);
} }
public class Test {
public static void main(String args[]) {
B b=new B();
C c=new C();
System.out.println(b.xB);
b.metodB();
System.out.println(c.xB);
c.metodB();
}}
çıktı :metodB:10
B nin constr. calisti
metodB:10
C sınıfındaki metodB:10
B nin constr. calisti
C nin constr. calisti
10
metodB:10
4
metodB:10
C sınıfındaki metodB:10
hocam peki bu kodun çıktısı niye böyle oluyor o zaman sonuçta C nin boş yapılandırıcısı çağrılmış fakat önce üst sınıfın boş yapılandırıcısı çalışmış daha sonra kendi yapılandırıcısını çağırmış sebebi başka bir sınıfta bu nesnelerin yaratılmış olması mı