Bölüm 4: Kalıtım

Bölüm 4: Kalıtım · Çalışma Soruları
extendsMetot aramasısuper ve yapıcı zinciriGeçersiz kılmaprotected ve finalis-a / has-atoStringequals ve hashCode
Sercan KÜLCÜ

Çoktan Seçmeli · Kalıtım Kavramı

Soru 1: Kalıtımla Alınmayan

class Kedi extends Hayvan yazıldığında Hayvan’ın hangi üyeleri Kedi’ye kalıtımla geçmez?

C: Yapıcılar kalıtımla alınmaz; alt sınıf yapıcısı üst sınıfınkini super(...) ile çağırır. private alanlar ise nesnede yer alır ama alt sınıftan doğrudan erişilemez; onlara üst sınıfın public/protected metotlarıyla ulaşılır.

Adım Adım Çalıştırma · Hayvan Örneği

Soru 2: Metot Hangi Sınıfta Bulunur?

Dört çağrının her biri için arama hangi sınıfta biter? Program ne yazar?

ObjecttoString() · equals(Object)CanlinefesAl() · tanit()Hayvantanit() · yemekYe()KediyemekYe()

k bir Kedi nesnesini gösterir. Oklar alt sınıftan üst sınıfa (extends) yönelir; en tepede Object vardır.

ObjecttoString() · equals(Object)CanlinefesAl() · tanit()Hayvantanit() · yemekYe()KediyemekYe()bulundu

Arama nesnenin gerçek sınıfı Kedi’de başlar: yemekYe() orada var, geçersiz kılınmış sürüm çalışır.

ObjecttoString() · equals(Object)CanlinefesAl() · tanit()Hayvantanit() · yemekYe()bulunduKediyemekYe()yok ↑

tanit() Kedi’de yok; bir üste çıkılır. Hayvan’ın sürümü bulunur ve arama durur; Canli’ninkine hiç bakılmaz.

ObjecttoString() · equals(Object)CanlinefesAl() · tanit()bulunduHayvantanit() · yemekYe()yok ↑KediyemekYe()yok ↑

nefesAl() iki sınıf yukarıda, Canli’de bulunur: kalıtım zincir boyunca geçer.

ObjecttoString() · equals(Object)bulunduCanlinefesAl() · tanit()yok ↑Hayvantanit() · yemekYe()yok ↑KediyemekYe()yok ↑

toString() hiçbir sınıfımızda yok: Object’in sürümü “sınıf adı@onaltılık kod” döndürür, yani true.

// p(s): System.out.println(s)
class Canli {
  void nefesAl() { p("Canlı nefes alır"); }
  void tanit() { p("Ben bir canlıyım"); }
}
class Hayvan extends Canli {
  @Override void tanit() { p("Ben bir hayvanım"); }
  void yemekYe() { p("Hayvan yer"); }
}
class Kedi extends Hayvan {
  @Override void yemekYe() { p("Kedi balık yer"); }
}
// main içinde:
Kedi k = new Kedi();
k.yemekYe();
k.tanit();
k.nefesAl();
System.out.println(k.toString().startsWith("Kedi@"));

Adım Adım Çalıştırma · Yapıcılar ve super

Soru 3: Yapıcı Zinciri: this ve super

new Taksi() dört yapıcıyı tetikliyor. Satırlar hangi sırayla yazılır?

YığınHeapTaksi()main()t?#1 Taksiteker0markanull

new önce tek bir nesne ayırır; üst sınıflardan gelen alanlar da dahil hepsi varsayılan değer alır.

YığınHeapTaksi(String)m"Fiat"Taksi()main()t?#1 Taksiteker0markanull

İlk satır this("Fiat"): aynı sınıfın öteki yapıcısı. Bir yapıcı ya this(...) ya super(...) ile başlar, ikisiyle birden değil.

YığınHeapAraba(String)marka"Fiat"Taksi(String)m"Fiat"Taksi()main()t?#1 Taksiteker0markanull

super(m) üst sınıf Araba’nın yapıcısını çağırır; o da hemen super(4) der.

YığınHeapArac(int)teker4Araba(String)marka"Fiat"Taksi(String)m"Fiat"Taksi()main()t?#1 Taksiteker4markanull

Arac (gizli super() ile Object() bittikten sonra) kendi alanını doldurur ve ilk satırı yazar.

YığınHeapAraba(String)marka"Fiat"Taksi(String)m"Fiat"Taksi()main()t?#1 Taksiteker4marka"Fiat"

Araba yapıcısı kaldığı yerden sürer: marka dolar, mesaj yazılır.

YığınHeapTaksi(String)m"Fiat"Taksi()main()t?#1 Taksiteker4marka"Fiat"

Taksi(String) gövdesinin kalanı: Taksi Fiat.

YığınHeapTaksi()main()t?#1 Taksiteker4marka"Fiat"

En son, ilk çağrılan Taksi() biter: Taksi. Yapıcılar üstten alta tamamlanır.

YığınHeapmain()t#1 Taksiteker4marka"Fiat"

t nesneyi gösterir; iki alan da üst sınıflardan kalıtımla gelmiştir: 4 Fiat.

class Arac {
  int teker;
  Arac(int teker) {
    this.teker = teker;
    System.out.println("Arac " + teker);
  }
}
class Araba extends Arac {
  String marka;
  Araba(String marka) {
    super(4);
    this.marka = marka;
    System.out.println("Araba " + marka);
  }
}
class Taksi extends Araba {
  Taksi() { this("Fiat"); System.out.println("Taksi"); }
  Taksi(String m) { super(m); System.out.println("Taksi " + m); }
}
// main içinde:
Taksi t = new Taksi();
System.out.println(t.teker + " " + t.marka);

Hata Bulma · Yapıcılar ve super

Soru 4: Eksik super(...)

Kod derlenmiyor. Hatanın nedeni nedir? super(ad); satırını this.no = no; satırının altına eklemek sorunu çözer mi? Doğru yapıcıyı yazın.

class Kisi {
  private String ad;
  Kisi(String ad) { this.ad = ad; }
}
class Ogrenci extends Kisi {
  private int no;
  Ogrenci(String ad, int no) {
    this.no = no;
  }
}
Cevabı göster
error: constructor Kisi in class Kisi
  cannot be applied to given types;
  required: String
  found:    no arguments

Yapıcı super(...) ile başlamıyorsa derleyici gizlice super(); ekler; Kisi’nin parametresiz yapıcısı yoktur.

Alta eklemek çözmez: error: call to super must be first statement in constructor.

Ogrenci(String ad, int no) {
  super(ad);
  this.no = no;
}

Kod Yazma · Yapıcılar ve super

Soru 5: super ile toString

Kisi sınıfında private String ad, Kisi(String ad) yapıcısı ve "Kisi: " + ad döndüren toString() var. Kisi’den türeyen, private int no alanı olan Ogrenci sınıfını yazın: yapıcı adı üst sınıfa versin; toString() üst sınıfın metnine " (no)" eklesin. Kisi k = new Ogrenci("Ece", 1203); System.out.println(k); ne yazar?

Cevabı göster
class Ogrenci extends Kisi {
  private int no;
  Ogrenci(String ad, int no) {
    super(ad);
    this.no = no;
  }
  @Override
  public String toString() {
    return super.toString() + " (" + no + ")";
  }
}

Çıktı: Kisi: Ece (1203). ad private olduğu için Ogrenci ona doğrudan erişemez; işi super(ad) ve super.toString()’e bırakır. Değişken Kisi tipinde olsa da Ogrenci’nin toString()’i çalışır.

Çoktan Seçmeli · Geçersiz Kılma

Soru 6: Parametresi Nokta Olan equals

Bu sınıf için hangisi doğrudur?

class Nokta {
  int x;
  @Override
  public boolean equals(Nokta n) {
    return x == n.x;
  }
}

A: Object’teki imza equals(Object)’tir. equals(Nokta) farklı parametre listesi olduğundan geçersiz kılma değil aşırı yüklemedir; @Override bunu yakalar: method does not override or implement a method from a supertype.

Çoktan Seçmeli · Geçersiz Kılma

Soru 7: Erişimi Daraltmak

Sekil’de public void ciz() var. Kare extends Sekil içinde void ciz() { } (belirleyicisiz) yazılırsa ne olur?

D: attempting to assign weaker access privileges; was public. Üst sınıf tipindeki her referans ciz()’i çağırabilmelidir; alt sınıf bu sözü bozamaz. Erişim aynı kalabilir ya da genişleyebilir.

Çıktı Sorusu · Geçersiz Kılma

Soru 8: super.yaz() İçinde ad()

B hem ad() hem yaz() metodunu geçersiz kılıyor; yaz() içinden super.yaz() çağrılıyor. Program ne yazar?

class A {
  String ad() { return "A"; }
  void yaz() { System.out.println("A:" + ad()); }
}
class B extends A {
  @Override String ad() { return "B"; }
  @Override void yaz() {
    System.out.println("B");
    super.yaz();
  }
}
// main içinde:
new B().yaz();
new A().yaz();
Cevabı göster
B
A:B
A:A
  • super.yaz() A’nın yaz() gövdesini çalıştırır ama nesne hâlâ bir B’dir.
  • O gövdedeki ad() aslında this.ad()’dır ve geçersiz kılınmış sürüm seçilir: "B".
  • new A().yaz() düz bir A nesnesinde: A:A.

Çoktan Seçmeli · Erişim ve Sınırlama

Soru 9: protected Kime Açık?

canli paketindeki Hayvan’da protected String isim; var. evcil.Kedi extends Hayvan içinde return isim;, alt sınıf olmayan diger.Bakici içinde return h.isim; yazılıyor. Hangisi doğrudur?

B: protected = sınıfın kendisi + aynı paket + alt sınıflar. Kedi başka pakette ama alt sınıftır. Bakici ne aynı pakette ne alt sınıf: isim has protected access in Hayvan.

Çoktan Seçmeli · Erişim ve Sınırlama

Soru 10: final ile Sınırlamak

Bu kodda kaç derleme hatası vardır?

class Hayvan {
  public final void nefesAl() { }
}
class Kedi extends Hayvan {
  public void nefesAl() { }
}
final class Sabit { }
class Deneme extends Sabit { }

C: final metot geçersiz kılınamaz (overridden method is final); final sınıftan alt sınıf türetilemez (cannot inherit from final Sabit). String, Math ve Integer da final sınıflardır.

Hata Bulma · Erişim ve Sınırlama

Soru 11: Görünümü Kısıtlanmış Nesne

Hangi satır derlenmez, neden? Satırı, nesne bir Lastik ise kislikMi()’nin sonucunu yazacak biçimde düzeltin.

class Parca {
  String seri;
  Parca(String seri) { this.seri = seri; }
  String seriNo() { return seri; }
}
class Lastik extends Parca {
  boolean kislik;
  Lastik(String seri, boolean kislik) {
    super(seri);
    this.kislik = kislik;
  }
  boolean kislikMi() { return kislik; }
}
// main içinde:
Parca p = new Lastik("XYZ-1", true);
System.out.println(p.seriNo());
System.out.println(p.kislikMi());
Cevabı göster
error: cannot find symbol
  symbol:   method kislikMi()
  location: variable p of type Parca

Hangi metotların çağrılabileceğine değişkenin tipi (Parca) karar verir; nesne bir Lastik olsa da Parca’da kislikMi() yoktur. p.seriNo() ise geçerlidir: XYZ-1.

if (p instanceof Lastik) {
  Lastik l = (Lastik) p;
  System.out.println(l.kislikMi());
}

Çıktı: XYZ-1, true.

Çoktan Seçmeli · Sınıflar Arası İlişkiler

Soru 12: is-a mı, has-a mı?

Hangi eşleştirmede ikisi de doğrudur?

B: “Her öğrenci bir kişidir” doğrudur → kalıtım (is-a). Kütüphanenin kitapları vardır → oluşum (has-a): kitaplar bir alanda tutulur. Araba bir motor değildir, motoru vardır; Kare bir Şekildir.

Çıktı Sorusu · Object Sınıfı

Soru 13: super.toString()

Kus toString()’i geçersiz kılmıyor. Program ne yazar?

class Hayvan {
  private String isim;
  Hayvan(String isim) { this.isim = isim; }
  @Override public String toString() {
    return "Hayvan[" + isim + "]";
  }
}
class Kedi extends Hayvan {
  private boolean evcil;
  Kedi(String isim, boolean evcil) {
    super(isim); this.evcil = evcil;
  }
  @Override public String toString() {
    return super.toString() + ", evcil=" + evcil;
  }
}
class Kus extends Hayvan {
  Kus(String isim) { super(isim); }
}
// main içinde:
Hayvan h = new Kedi("Tekir", true);
System.out.println("Kayıt: " + h);
System.out.println(new Kus("Maviş"));
Cevabı göster
Kayıt: Hayvan[Tekir], evcil=true
Hayvan[Maviş]
  • "Kayıt: " + h birleştirmede toString() kendiliğinden çağrılır; nesne bir Kedi olduğu için onun sürümü çalışır ve super.toString() ile başlar.
  • Kus’ta toString() yok: arama bir üste çıkar, Hayvan’ınki bulunur. Object’in Kus@1b6d3586 biçimindeki sürümüne inilmez.

Adım Adım Çalıştırma · Object Sınıfı

Soru 14: equals’ın İçinde

equals her çağrıda hangi satırda biter? Program ne yazar?

YığınHeapmain()abc#1 Noktax1y2#2 Noktax1y2

İki ayrı nesne, içerikleri aynı. c = a yeni nesne oluşturmaz: a ve c aynı nesneyi gösterir.

YığınHeapmain()abc#1 Noktax1y2#2 Noktax1y2

== referansları karşılaştırır: #1 ile #2 farklı nesneler → false.

YığınHeapequals(Object o)thisodmain()abc#1 Noktax1y2#2 Noktax1y2

this = #1, o = #2. Aynı nesne değil; o instanceof Nokta doğru; aşağı dönüşümle d aynı nesneyi Nokta olarak görür.

YığınHeapequals(Object o)thisodmain()abc#1 Noktax1y2#2 Noktax1y2

Alanlar karşılaştırılır: 1 == 1 ve 2 == 2 → true. İçerik eşitliği.

YığınHeapequals(Object o)thisomain()abc#1 Noktax1y2#2 Noktax1y2

a.equals(c): this == o doğru; hızlı yol, hemen true.

YığınHeapequals(Object o)thisomain()abc#1 Noktax1y2#2 Noktax1y2#3 Stringdeğer"1,2"

o bir String: instanceof Nokta yanlış → false. Dönüşüme hiç gelinmediği için ClassCastException oluşmaz.

class Nokta {
  int x, y;
  Nokta(int x, int y) { this.x = x; this.y = y; }
  @Override public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Nokta)) return false;
    Nokta d = (Nokta) o;
    return x == d.x && y == d.y;
  }
}
// main içinde:
Nokta a = new Nokta(1, 2), b = new Nokta(1, 2);
Nokta c = a;
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(a.equals("1,2"));

Çoktan Seçmeli · Object Sınıfı

Soru 15: hashCode Unutulursa

Nokta equals metodunu doğru biçimde geçersiz kılıyor ama hashCode’u kılmıyor. Program ne yazar?

HashSet<Nokta> kume = new HashSet<>();
kume.add(new Nokta(3, 4));
kume.add(new Nokta(3, 4));
System.out.println(kume.size() + " "
    + new Nokta(3, 4).equals(new Nokta(3, 4)));

A: HashSet önce hashCode ile kova seçer, sonra yalnızca aynı kovadakileri equals ile karşılaştırır. Object’in hashCode’u iki ayrı nesneye (pratikte) farklı değer verir; eşit noktalar hiç karşılaştırılmaz ve iki kez eklenir. Derleyici bunu denetlemez. Kural: equals geçersiz kılınıyorsa hashCode da kılınmalı (ör. Objects.hash(x, y)).

Çoktan Seçmeli · Object Sınıfı

Soru 16: null ve instanceof

Kedi extends Hayvan. Hayvan h1 = new Kedi(); Hayvan h2 = null; için h1 instanceof Hayvan, h1 instanceof Object ve h2 instanceof Hayvan sırasıyla nedir?

D: Alt sınıf nesnesi üst sınıfların da örneğidir; her nesne bir Object’tir. null hiçbir nesneyi göstermez, instanceof her zaman false verir. Bu yüzden instanceof kullanan equals ayrıca null kontrolüne ihtiyaç duymaz.

Son

Bölüm 4: Kalıtım: Çalışma Soruları
Konu anlatımı: kalıtım sunumu · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.