Java - Kalıtım (Inheritance)

Java - Kalıtım (Inheritance)

Inheritance(Miras Alma)

Inheritance yardımıyla sınıflar arası hiyerarşi oluşturmak ve ortak özellikleri başka sınıflara aktarmak mümkündür.Kalıtımı sağlamak için Java'da extends ifadesini kullanırız.

  1. Bir sınıf birden çok miras alamaz.

  2. Bir sınıf bir üst sınıftan miras aldığında, tüm public ve protected members otomatik olarak alt sınıfın bir parçası olarak kullanılabilir.

  3. Alt sınıf, üst sınıfla aynı paketteyse, package-private üyeler kullanılabilir.

  4. Son olarak, private üyeler tanımlandıkları sınıfla sınırlıdır ve hiçbir zaman kalıtım yoluyla kullanılamazlar.

  5. Bu, üst sınıfın veri tutabilen veya bir nesneyi değiştirebilen private üyelere sahip olmadığı anlamına gelmez; bu sadece alt sınıfın onlara doğrudan referansı olmadığı anlamına gelir.

Java'da, sınıfı final ile işaretleyerek bir sınıfın genişletilmesini önlemek final sınıftan miras alan bir sınıf tanımlamaya çalışırsanız sınıf derlenmez.

Java'da her class java.lang.Object'den türer.

BigCat sınıfında size public olarak işaretlendiği için Jaguar bu alanı kendi boyutuymuş gibi okuyabilir ve yazabilir.

public class BigCat {

  public double size;

}

public class Jaguar extends BigCat {

    public Jaguar() {
        size = 10.2;
    }

    public void printDetails() {
        System.out.println(size);
    }
}
public class Animal {

    private int age;
    protected String name;

    public int getAge() {
        return age;
    }

    public void setAge(int newAge) {
        age = newAge;
    }

}

public class Lion extends Animal {

public void setProperties(int age, String n) {
        setAge(age);
        name = n;
}

public void roar() {
        System.out.print(name + ", age " + getAge() + ", says: Roar!");

        // System.out.print("Lions age: " + age); // DOES NOT COMPILE
        // Animal class'ında age private olduğu için doğrudan derlenmez.
}

    public static void main(String[] args) {
        var lion = new Lion();
        lion.setProperties(3, "kion");
        lion.roar();
    }

}

Java'da üst düzey bir sınıf, başka bir sınıf içinde tanımlanmayan bir sınıftır.

Yalnızca public veya package private erişimine sahip olabilirler. Bir sınıfa public erişim uygulamak, herhangi bir sınıfta çağırılabileceğini ve kullanılabileceğini gösterir.

Herhangi bir erişim değiştiricisinin olmaması default (package-private) erişimin uygulanması sınıfa yalnızca aynı paket içindeki bir sınıf tarafından erişilebileceğini gösterir.

this Kullanımı

  1. Aynı sınıftaki diğer bir kurucuya , super() ise üst sınıftaki bir kurucuya yapılan çağrıdır.
  2. this içinde bulunan bir kurucuya referansdır.
  3. this bir metoda geçilebilir ve bir metottan geri döndürülebilir,fakat super için bunlar geçerli değildir.
  4. Sadece constructor(kurucu) metodları çağırılabilir.
  5. Kendisini çağıramaz.
  6. Recursive olarak kullanılamaz.

Java en ayrıntılı kapsamı kullanır, bu nedenle, color = color olduğunda,metodun parametre değerini kendisine atadığınızı düşünür.

Assigment, method içinde başarıyla tamamlanır, ancak color instance variable'ın değeri hiçbir zaman değiştirilmez ve main() method yazdırıldığında null olur.

instance variable aynı ada sahip local variable olduğunda "this" referansını veya anahtar sözcüğünü kullanmak sorunu çözer.

this referansı, sınıfın mevcut instance'ına atıfta bulunur ve devralınan üyeler de dahil olmak üzere sınıfın herhangi bir üyesine erişmek için kullanılabilir.

Method, constructor, and instance initializer bloklarında kullanılabilir , fakat static method veya static initializer bloklarında kullanılmaz.

public class Flamingo {

  private String color;

  public void setColor(String color) {
        // color = color;
        this.color = color;
  }

  public static void main(String... unused) {
        Flamingo f = new Flamingo();
        f.setColor("PINK");
        System.out.println(f.color);
    }
}
public class Duck {

    private String color;
    private int height;
    private int length;

    public void setData(int length, int theHeight) {

        length = this.length; // yanlış
        height = theHeight; //  farklı isim olduğu için this gerekli değildir.

        this.length = length;
        this.color = "white";
    }

    public static void main(String[] args) {
        Duck b = new Duck();
        b.setData(1, 2);
        System.out.print(b.length + " " + b.height + " " + b.color); // 1 2 white
    }

}

super Kullanımı

  1. super sadece nesne metotlarında ,nesne başlatma blokların da,kurucularda yada nesne değişkenine atamada kullanılabilir.
  2. Örneğin super static bir bağlamda kullanılamaz.
  3. super sadece hemen bir üstteki sınıfa ulaşmak için kullanılır.
  4. super() ise üst sınıftaki bir kurucuya yapılan çağrıdır.
  5. super ile hem sınıf hem nesne üyelerine ulaşılır.
public class Animal {
    protected int age;
    protected String name;

    public Animal(int age, String name) {
        super(); // herhangi bir sınıftan miras almadığı için  buradaki super
    // Java.lang.Object içinde tanımlanan ve hiçbir argüman almayan üst yapıcıya  yapılan bir çağrıdır.
        this.age = age;
        this.name = name;
    }

    public static void main(String[] args) {
        System.out.println("Animal is created");
    }

    public Animal(int age) {
        super();
        this.age = age;
        this.name = null;
    }

}

İlk alt kurucu bir argüman alır, age ve iki argüman alan, age ve name olan ana kurucuyu çağırır.

Alt kurucuların eşleşen üst kurucuları çağırmasının gerekmediğine dikkat edin. Ana kurucuya uygun giriş parametreleri sağlandığı sürece herhangi bir geçerli ana kurucu kabul edilebilir.

public class Gorilla extends Animal {

    public Gorilla(int age) {
        super(age, "Gorilla");
        super.age = age; // üst sınıftaki üyesini (field) çağırır.
    }
}

Birinci, super parent sınıfın üyelerine başvurmak için kullanılırken,ikincisi, super(), bir üst constructor'ı çağırır.

public Gorilla() {
        super(5); // get constructor
}

Java'da, hem bir üst sınıfta hem de bir alt sınıfta aynı isimle bir variable veya method tanımlanabilir.

Bu olduğunda, geçerli sınıf yerine üst sınıftaki field yada methodu nasıl çağırır ?

Başka bir deyişle, üyeye kalıtım yoluyla erişilebilir olmalıdır. Aşağıda ki sınıf bir method'da aynı ada sahip iki variable'ı kullanmak için super'in nasıl uygulanacağını gösterir.

class Mammal {
    String type = "mammal";
}

public class Bat extends Mammal {

    String type = "bat";

   public String getType() {
        return super.type + ":" + this.type;
 }

    public static void main(String... zoo) {
        System.out.print(new Bat().getType()); // mammal:bat
    }
}

super kaldırılır ise bu sınıfta bat:bat yazdırılır. Java yapabileceği en dar kapsamı kullanır. Bu durumda Bat sınıfındaki type değişkenini alır.

class Insect {
    protected int numberOfLegs = 4;
    String label = "buggy";
}

public class Bettle extends Insect {

  protected int numberOfLegs = 6;
  short age = 3;
}

public void printData() {
    System.out.print(this.label);
    System.out.print(super.label);
    System.out.print(this.age); // this. mevcut ve inherit devralınan üyeleri içerir. super sadece inherit olanları alır.

// System.out.print(super.age); // sadece mevcut class'da tanımlı this erişebilir super erişemez.

System.out.print(numberOfLegs);

        /**
         * Beetle'da her iki sayıdaki numberOfLegs değişkenine erişilebilir olsa da,
         * Java en dar kapsamdan başlayarak dışa doğru kontrol eder. Bu nedenle Beetle
         * sınıfındaki numberOfLegs değeri kullanılır ve 6 yazdırılır.
         * 
         * Bu, devralınan üyeleri içerdiğinden, genellikle yalnızca devralma yoluyla bir
         * adlandırma çakışması olduğunda super kullanırsınız.
         */
}

public static void main(String[] args) {
        new Bettle().printData();
}