Nested Class da Shadowing durumu
Merhaba Arkadaslar,
8.bolumde Java’da bulunan Nested Class konusunu incelecegiz.
Java dili bir sinif icerisinde bir baska sinif tanimlamaniza izin verir. Bu kavrama genel olarak Nested Class denilir.
Nested Class’lar 2 ye ayrilir ; static ve non-static . static tanimli nested class’lara static nested class denilir. non-static nested classlar ise inner class olarak isimlendirilir.
1. Non-Static Nested Class(Inner Class)
· Regular Inner Class
· Local Inner Class
· Anonymous Inner Class
2. Static Nested Class
Ilk olarak Regular Inner Class ile baslayalim, yazi boyunca Regular Inner Class’lara Inner Class diyecegiz.
public class OuterClass {
class InnerClass {
}
static class StaticNestedClass {
}
}
Bir nested class , outer sinifin uyesidir(member) . Non-static nested class(inner class) , outer sinifin uyelerine(instance variable ve metotlar) ulasabilir. Bu uyeler private tanimli bile olsa bu ulasim soz konusudur. Bunun tersi de gecerlidir yani Outer class’tan Inner class in instance degiskenlerine erisim saglanabilir.
Nested Class’lar , outer/dis siniflarin bir uyesidir. Bir sinifin uyeleri 3 access modifier’a da sahip olabilir(Dolayisiyla 4 access level’e sahip olabilir) . Bu nedenle Nested Class’lar private, protected veya public olarak tanimlanabilir.
Unutmayalim ki outer siniflar ise sadece public anahtar kelimesini kullanabilir ya da package level olarak tanimlanabilir fakat private veya protected anahtar kelimesini sinif tanimlamasinda kullanamayiz. Class Declaration konusunu 1.bolumde islemistik.
Nested Class nedir ve nasil tanimlanir sorusuna yanit aradik, peki nested class’lar neden kullanilir ?
Mantiksal Grouplama(Logically Grouping)
Eger bir nested class sadece bir sinif icin kullanisli/useful durumda ise mantiksal olarak bu 2 sinifi (outer ve inner) bir arada tanimlamak ve tutmak yerinde olacaktir. Nested Class’lar bir nevi yardimci siniflardir , bunlari package level olarak tanimlamak yerine ilgili sinifin uyesi olarak tanimlamak daha uygun olacaktir.
Encapsulation arttirimi
Outer ve Inner siniflarini dusunelim. Inner sinifi Outer sinifinin private uyesine erisebilir.
Inner sinifin kendisi de diger siniflardan gizli durumda olacaktir.
Readable(Okunabilirlik) and maintainable(surdurulebilirlik) kod
Outer class ile Nested Class yapisi icice birbirine yakin olacagi icin kodun okunabilirlik ve surdurulebilirlik ozelligi artacaktir.
Nested Class iceren kaynak dosyayi(.java) , derledigimiz zaman hem outer class hem nested class icin derlenmis (.class uzantili ) dosya olusur. Nested Class’larin isimlendirilmesi sekli Outer_Class_Ismi$Nested_Class_Ismi.class seklinde olacaktir. Ornegin yukaridaki kodumuzu derledigimiz zaman su dosyalar olusur ;
OuterClass.class
OuterClass$InnerClass.class
OuterClass$StaticNestedClass.class
.class uzantili dosyalari , projenizde bin klasoru altinda gorebilirsiniz.
Non-Static Nested Class(Inner Class)
Non-Static Nested Class’lara , inner class denilir. Bir inner class’in ornegi/instance , outer class’in orneginin hali hazirda mevcut olmasi ile mumkundur. Yani outer class’tan bir obje olusturmadigimiz surece , inner class’in objesi olusamaz.
Hatirlayacagimiz gibi bir sinifin uyeleri(instance variable ve instance method) ancak ilgili sinifin objesi/instance/ornegi oldugu zaman anlam kazanir. Cunku instance degiskenler ve instance method’lar objeye/instance aittir. Benzer sekilde inner class da outer class in uyesidir , dolayisiyla outer class in objesi/instance/ornegi gereklidir.
public class OuterClass {
public static void main(String[] args) {
OuterClass outerRef = new OuterClass();
// InnerClass'a ait bir obje/instance olusturmak icin oncelikle
// OuterClass tipinde bir obje/instance olusturuyoruz.
// InnerClass a ait ornegi/instance/objeyi su sekillerde
// olusturabiliriz.
InnerClass innerRef = outerRef.new InnerClass();
OuterClass.InnerClass innerRef2 = outerRef.new InnerClass();
InnerClass innerRef3 = new OuterClass().new InnerClass();
OuterClass.InnerClass innerRef34 = new OuterClass().new InnerClass();
}
void createInnerClassInstance() {
InnerClass innerClass = new InnerClass();
// Instance Metot'tan bahsedebilmek icin OuterClass tipinde objenin
// varligi gerekmektedir.
// Dolayisiyla non-static metot'da InnerClass tipinde objeyi bu sekilde
// olusturabiliriz.
}
class InnerClass {
}
}
· Inner Class , Outer Class’ta bulunan degiskenlere(instance variable veya static variable) erisim saglayabilir.Bu degiskenler private bile olsa erisim saglanir.
· Inner Class , Outer Class’ta bulunan metotlara(instance metotlara veya static metotlara) erisim saglayabilir. Bu metotlar private bile olsa erisim saglanir
· Benzer sekilde Outer Class, Inner Class’in degiskenlerine ve metotlarina erisim saglayabilir. Bu degiskenler ve metotlar private olsa bile erisim saglanir.
public class OuterClass2 {
private String privateVariable = "i am private instance variable";
private static String privateStatic = "I am private static variable";
public static void main(String[] args) {
OuterClass2.InnerClass2 innerRef = new OuterClass2().new InnerClass2();
innerRef.innerTestMethod();
System.out.println(innerRef.privateInnerVariable);
}
private void outerTestMethod() {
System.out.println("Outer Test Method");
}
private void outerStaticTestMethod() {
System.out.println("Outer Static Test Method");
}
class InnerClass2 {
private String privateInnerVariable = "I am private inner variable";
private void innerTestMethod() {
System.out.println(privateVariable);
System.out.println(privateStatic);
outerTestMethod();
outerStaticTestMethod();
}
}
}
Inner classlarda static degiskenler sadece final olarak tanimlanabilir. Buna ragmen final olacak sekilde bir static metot tanimlanamaz.
public class OuterClass3 {
class InnerClass3 {
private static final String staticVariable = "Static Inner Class Variable";
// inner class icerisinde static degisken final olmalidir.
// inner class icerisinde static metot tanimlayamayiz.
// private final static void innerStaticMethod(){ } //derleme hatasi
}
}
Icice birden fazla inner class tanimlanabilir.
public class OuterClass4 {
class InnerClass {
class InnerClass2 {
}
}
}
Shadowing
Hatirlayacagimiz gibi bir sinifta instance variable ve local variable ayni isme sahipse bu durumda shadowing durumu ortaya cikmaktaydi.Bu durumda instance variable’a ulasmak icin this anahtar kelimesinden yararlanmaktaydik. Hatirlayacagimiz gibi this anahtar kelimesi hali hazirda ilgili objeyi referans almaktadir.
Benzer shadowing durumu Outer class ve Inner class icin de soz konusudur. Yani outer class’ta tanimli bir instance degisken ile inner class’ta bulunan bir degiskenin ismi ayni olursa ortaya shadowing durumu cikacaktir.
Oncelikle shadowing konusunu bir ornek ile hatirlayalim
public class ShadowingTest {
String shadowing = "I am instance variable";
public static void main(String[] args) {
ShadowingTest st = new ShadowingTest();
st.shadowingTest();
}
void shadowingTest() {
String shadowing = "I am local variable";
System.out.println(shadowing);
System.out.println(this.shadowing);
}
}
this anahtar kelimesi inner class icerisinde oldugu icin inner class a ait olan objeye referans edecektir. Bunun icin outer classta yer alan shadowinge neden olan degiskene OuterClassName.this.InnerClassName.shadowingVariable seklinde ulasim saglanabilir.
public class ShadowingOuter {
private String shadowing = "Outer Test";
public static void main(String[] args) {
InnerClass innerClass = new ShadowingOuter().new InnerClass();
innerClass.printTest();
}
public class InnerClass {
private String shadowing = "Inner Test";
public void printTest() {
System.out.println(shadowing);
System.out.println(this.shadowing);
// this anahtar kelimesi inner class icerisinde oldugu icin inner
// class a ait olan objeye referans edecektir.
// Bunun icin outer classta yer alan shadowinge neden olan degiskene
// OuterClassName.this.InnerClassName.shadowingVariable
// seklinde ulasim saglanabilir.
System.out.println(ShadowingOuter.this.shadowing);
}
}
}
inner class sinif uyeleridir bu nedenle private, protected , public gibi access modifierlari alabilirler. Benzer sekilde abstract , final ,static olarak tanimlanabilir(static tanimlandiginda artik inner class olarak isimlendirilmez , static nested class olarak isimlendirilir)
public class Outer {
private class Inner {
}
class SubInner extends Inner {
}
final class FinalInner {
}
// class CanNotExtendsFinalClass extends FinalInner {}
class SubInner2 extends Outer {
}
abstract class AbstractInnerClass {
}
}