1.2.1 Overloaded Methods and constructors
1.3 Method Overriding and Virtual Method Invocation
1.3.1 Need of overridden methods
1.3.2 Correct Syntax of overriding methods
1.4 Overriding methods of class object
1.5 Casting and the instanceof operatör
Public > Protected > Default(Package) > Private
Bir sınıf kendi metodunu veya base class’ından inherit ettiği metodları Overload edebilir. Bir metodu overload etmek için parametre listesi değiştirilir. Bunlar;
Overloaded sayılmayan durumlar ise;
Return Type (Sadece dönüş tipi farklı 2 metod tanımlarsak “Duplicate method” hatası alırız. Bu durum metodlar aynı sınıf içinde veya biri base class’da diğeri extended class’da olduğu durumlarda geçerlidir.)
Access Modifier
Nonaccess Modifier
Constructor’lar da overload edilebilir. Özellikleri yukardakiler ile aynıdır. Tek fark “Using nonaccess modifiers with constructors is illegal—the code won’t compile.” Overload edilen constructor’lar ise sınıfın kendisini temsil eden “this” keyword ile çağrılabilir. Ayrıca bu keyword constructor içindeki ilk cümle olmak zorundadır. This ile çağrılabilen constructor’lar sınıftaki başka metodlardan çağrılamaz, sadece contructorlardan çağrılabilir. Ayrıca sadece access modifier değiştirerek overloaded constructor yazılamaz. Yukardaki kuralın aynısı. Fakat farklı Access modifier kullanılarak overloaded constructor yazılabilir.
Ayrıca bir yapıcı kendini çağıramaz. Çağırırsa compiler “recursive constructor invocation” hatası verir ve derlenmez. Aynı şekilde bir yapıcı diğerini çağırır diğeri de onu çağıranı çağırırsa buna da izin vermez ve aynı hatayı verir.
Sınıf hafızada yaratılırken initialize olma sırası aşağıdaki gibidir. En alta “Child Static initialization” ve onun da altına “Parent Static initialization” yazılabilir. Bütün sıra bu şekildedir. Sıra;
Parent Static initialization
Child Static initialization
Parent instance initialization
Parent constructor
Child instance initializer
Child constructor
Bir sınıf inherit ettiği sınıftaki bir metodu yeniden tanımlayabilir. Bu yeniden tanımlamaya “Method Overriding” denir. Overriding methods =Polymorphic methods. Override etmek için method imzasının aynı olması gerekmektedir.(method name, method parameder number and method parameter type) Instance methodlar override edilir. [Static metodlar override edilemez!] İstenirse Derivated da saklanabilir.
Base class method = Overridden method
Derived class method = Overriding method
Bu base class’daki yeniden tanımlanabilen methodlar “virtual method” olarak adlandırılır.(A method that can be overridden by a derived class is called a virtual method) “Virtual method invocation” ise override edilen doğru methodu çağırma işidir. Bu ise nesnenin referansı ile değil, bu referansın gösterdiği nesnenin bellekteki gerçek tipi ile yapılır. Bu sebepten doğru metodu çağırma işi [Runtime da belirlenir], Compile time’da değil!
Overriden metodlar şu ilkelere göre çalışır;
Yani sınıf derlenirken metodu kontrol etmek için referans tipe bakarak bu referans tipinin geçilebileceği metod varmı diye bakar. Runtime da ise hangi metodun çağrılacağını referans tipinin gösterdiği gerçek objenin tipine bakarak karar verir. Eğer override edilmiş bir method var ise bunu bilir ve objenin sınıfındaki metodu çalıştırır!
Method override etmek için bazı kurallar vardır.
Overloading - Referance Variable - Type Compile Time’da metodu belirler.
Overriding - Variable Type - Runtime’da metodu belirler.
Override etmek için metodun derivated tarafından ulaşılabilir olması ve static olmaması gerekmektedir. Eğer Static metod override edilir ise derivated base deki metodu saklar. Ayrıca static metodlar compile time da bağlandığı için referans variable type a bakar ve ref. Var. Type daki metodu çalıştırır. (Base de static metod derivated da instance metod veya tam tersi derlenmez.) Ayrıca Constructor lar inherit edilmediğinden override edilmezler!!
Bu 3 konsept şu şekilde özetlenebilir;
toString() = default olarak sınıf Adı @ işareti ve hasCode fonksiyonu değerini gösterir. Bu metodu düzgün override etme kuralları; Herhangi bir sınıfa ait herhangi bir text döndürmemelidir.(Mesela sınıfın ismi veya sınıftaki statik bir değişken) Mesela instance değişkenin ismini yazdırabilir.
Public String toString()
equals() = default olarak bellekteki aynı objeyi gösterirse iki referans variable, o zaman true döndürür.
Public boolean equals(Object obj)
hashCode() = Bu metod nesnenin hash kodunu döndürür. HashCode fonksiyonu özellikle Collection sınıflarında değerleri bulmak için kullanılır. İyi yazılmış bir hashCode fonksyonu nesneleri eşit olarak farklı kovalara koyar. Kova kavramı şudur: Bir map yapısı var. Bir değeri bulmak için nesnenin önce hashKodu bulunur. Her nesne hashCode’un gösterdiği değere ait kovada bulunur. Aynı hashCode lu nesneler aynı kovada durur. Aynı koadaki nesneler ise equals fonksiyonu ile birbirinden ayrılır ve dopru değer bulunur. Kuralları şu şekildedir;
HashMap de arama yaparken override edilen hashCode metodu kullanılır. Bu metod çok iyi override edilmelidir. Yoksa derleme hatası alınmaz ama kod doğru çalışmaz. Yukardaki kurallar uygulanmalıdır. Mesela aynı nesne üzerinde birden fazla hashCode çağırıldığında da aynı sonuç alınmalıdır. Ayrıca hashCode sabit değer döndürmemeli, mümkünse farklı değerler döndürmelidir. Ayrıca Collection keyleri immutable(değişmez) olmalıdır. Yoksa aynı nesneyi tekrar bulmak imkansız olur.
public native int hashCode();
Implicit = Üstü kapalı, ima edilen
Explicit = Açık, belirgin
BaseClass b = new ExtendedClass(); //Bu satırlar Implicit Casting
Interface i = new ExtendedClass();
SubClass’ların nesneleri base class’larının veya base interfacelerinin referance variable’larına cast edilebilir.
Yukardaki örnekte i.description() çalışmaz. Çünkü compiler referans değişken tipine bakar ve interface de description metodu olmadığını görür.(print dese ne oldurdu?) Kod compile olmaz. Bunu aşmak için (ExtendedClass)i diyerek aşabiliriz.
((Extended)i).description //Bu satır Explicit Casting
Burada compilera bu referans tipi değişkeni içindeki tipi biliyorum ve git o class’ın metodlarına bak demek anlamına geliyor.
Casting
Implicit Casting | Explicit Casting | |
---|---|---|
Upcasting | Yukarıdaki örnek | Yukardaki örnek ((ExtendedClass)i).description() |
Downcasting | ExtendedClass e = new Base(); Yukardaki satır hatarlıdır, derlenmez. Tersi ise çalışmaz. | BaseClass b = new BaseClass();ExtendedClass e = (ExtendedClass) b ;AnotherInterface a = (AnotherInterface) b ;Yukardaki 3 satırda derlenir ama runtime’da ClassCastException fırlatır. Son satırda interface implemente edilmese bile hata vermez!!! |
Her zaman ClassCastException fırlatır |
İmplement etmeyen final class’lar explicitcast yapılamaz.
Null ile compilation ve runtime hatası almadan explicit cast yapılabilir. (BaseClass)null gibi.
{width=”6.3in” height=”3.9930555555555554in”}
instanceof ()
Öncelikle bu keyword deki o harfi küçük, buna dikkat et.
null instanceof Class Her zaman false döndürür.
Buradaki null ile Class sınıfları birbirlerine “inconvertible” ise kod derlenmez.
Instanceof asla runtime exception fırlatmaz. True yada false döndürür. Uyumlu değil ise compile olmaz zaten.
<referanceVariable> instanceof <ClassName>
Package keyword’ü her zaman sınıfın/interface ‘in ilk satırıdır(Yorumlar hariç) ve bir tanedir. (Anlaşma olarak hepsi küçük harf olmalıdır.)
ClassPath = JRE’nin bir sınıfı çalıştırmak için arayacağı klasörlerdir.(Bir txt ile mutlaka dene)
import kelimesi sadece farklı paketteki sınıfı classımıza kolayca, kısa şekilde temsil etmemizi sağlar. İçeriğini sınıfımıza import etmez.
java.lang paketi bütün sınıflara otomatik olarak eklenir.
Aynı sınıf isimli iki farklı package’daki sınıflar aynı sınıfa import edilemez. Edilirse kod derlenmez. (java.util.Date ve java.sql.Date gibi)
Her sınıf ayrı ayrı import edilebildiği gibi * koyularak hepsi de import edilebilir.(Alt package’lar hariç. Sub package sınıfları import olmaz.)