OCA Java imtahan mövzuları

Calling Constructors and Inherited Class Members

Calling Constructors

Java`da parent constructor həmişə child constructordan əvvəl icra olunur:

class Continent {
    public Continent() {
        System.out.println("Continent");
    }
}

class Country extends Continent {
    public Country() {
        System.out.println("Country");
    }
}

class City extends Country {
    public static void main(String[] args) {
        new City();
    }
}

Output:

    Continent
    Country

Compiler əvvəlcə ContinentCountry constructorlarının birinci sətrinə super() əlavə edir. Sonra City classına default no-argument constructor əlavə edir və birinci sətrinə də super(). Bu səbəbdən də parent constructorlar ilk öncə icra olunur.

 

 

Calling Inherited Class Members

Child classlar parent classın istənilən publicprotected üzvlərini (members) istifadə edə bilər. Əgər parent və child class eyni paketdə olarsa, o zaman parent classın default üzvlərini də istifadə edə bilər. Amma parent classın private üzvlərinə heç vaxt birbaşa müraciət edə bilməz. private üzvlərə public və ya protected metodlar vasitəsilə dollayı yolla müraciət etmək olar:

class Fish {

    protected int size;
    private int age;

    public Fish(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }
}

class Shark extends Fish {

    private int number = 8;

    public Shark(int age) {
        super(age);
        this.size = 7;
    }

    public void displaySharkDetails() {
        System.out.println("Shark age: " + getAge());   // 1
        System.out.println("Shark size: " + size);      // 7
        System.out.println("Shark number: " + number);  // 8
    }

    public static void main(String[] args) {
        new Shark(1).displaySharkDetails();
    }
}

Child classda biz parent classın public metodunu (getAge()) və protected dəyişənini (size) birbaşa istifadə edə bilərik. Ümumiyyətlə, varisliyə görə child class parent classın bütün üzvlərinə sahiblənir, yəni miras alır (access modifier`in icazə verdiyi üzvlər). Buna görə də biz child classda this açar sözündən istifadə edərək həm child classın, həm də parent classın üzvlərini çağıra bilərik. Yuxarıdakı metod ilə bu metod mahiyyət baxımından eynidir:

public void displaySharkDetails() {
    System.out.println("Shark age: "    + this.getAge());  // 1
    System.out.println("Shark size: "   + this.size);      // 7
    System.out.println("Shark number: " + this.number);    // 8
}

Biz parent classın üzvlərini super açar sözünü istifadə edərək də çağıra bilərik, amma super vasitəsilə cari classın üzvlərini çağıra bilmərik. Başqa sözlə thissuper ilə həm parent class, həm də child classın üzvlərini çağıra bilərik, amma cari classın üzvlərini ancaq this ilə çağırmaq mümkündür, əks halda compile xətası verəcək:

public void displaySharkDetails() {
    System.out.println("Shark age: "    + super.getAge());   // 1
    System.out.println("Shark size: "   + super.size);       // 7
    System.out.println("Shark number: " + this.number);      // 8
    System.out.println("Shark number: " + super.number);     // DOES NOT COMPILE
}

 

MyExamCloud test suallarının içərisində təxminən belə bir nümunə ilə rastlaşmışdım, output`un nə olacağı soruşulurdu:

package packageA;

public class A {
    protected int y = 10;
}
package packageB;

import packageA.A;

public class B extends A {
    int y = 5;
    public void print() {
        A a = new A();
        System.out.println(a.y + y);
    }
}

İlk baxışdan sadə görünür. Yuxarıda da qeyd etdik ki, child class parent classın protected üzvlərini istifadə edə bilər. Bu qaydaya istinad edərək suala yanaşdıqda ağlımıza gələn ilk cavab 15-dir. Amma sualda çox incə bir nüans var, bəlkə də bu sertifikat sualları içərisində ən çaşdırıcı məqamlardan biridir. Əslində kod nümunəsi compile olunmur və səbəb protected açar sözünün istifadəsi ilə bağlıdır. Əgər parent və child classlar fərqli paket(package)lərdədirsə, parent classdakı protected üzvlərə child classda ancaq child classın referansı vasitəsilə müraciət oluna bilər, parent classın öz referansı vasitəsilə müraciət edilə bilməz. Yuxarıdakı kod nümunəsində gördüyünüz kimi B classında A classının y dəyişəninə A classının öz referansı vasitəsilə müraciət edilir (a.y), bu səbəbdən də bu sətir compile xətası verir. Əgər B classının referansı vasitəsilə müraciət edilsə, xəta verməyəcək.  Amma bu nümunədə həm A, həm də B classında istifadə edilən dəyişən adı eyni olduğundan burada y dəyişənini B classının referansı vasitəsilə çağırsaq, B classına məxsus y dəyişəninə müraciət ediləcək.

Yuxarıdakı kod nümunəsi üzərində biraz dəyişiklik edib, protected üzvlərə necə müraciət edə bilərik baxaq:

package packageA;

public class A {
    protected int k = 10;
    protected int n = 15;
}
package packageB;

import packageA.A;

public class B extends A {
    int k = 5;
    
    public void print() {
        A a = new A();
        B b = new B();
        System.out.println(k + b.k);      // 10
        System.out.println(k + super.k);  // 15
        System.out.println(k + b.n);      // 20
        System.out.println(k + a.n);      // DOES NOT COMPILE
    }
    
    public static void main(String[] args) {
        B b = new B();
        b.print();
    }
}

 

 

super() vs super

thisthis() ifadlərinin bir-biri ilə əlaqəsi olmadığı kimi, supersuper() ifadələri də bir-birindən tamamilə fərqlənir.

Düzgün istifadə qaydası:

public Book(int age) {   // constructor
    super();    
    super.setAge (10);
}

Səhv istifadə qaydası:

public Book(int age) {
    super;                 // DOES NOT COMPILE
    super().setAge (10);   // DOES NOT COMPILE
}

Aşağıdakı kod nümunəsini Enthuware testlərindən götürmüşəm, amma kodun daxilini biraz dəyişmişəm, daha maraqlı ola biləcək bir fakt əlavə etmişəm:

class Doll {
    String name;
    Doll(String nm) {
        this.name = nm;
    }
}

class Barbie extends Doll {
 // String name;        // line1 
    Barbie(){
        this(name);     // DOES NOT COMPILE
    }
    Barbie(String nm){
        super(name);    // DOES NOT COMPILE
    }
}

public class Test {
    public static void main(String[] args) {
        Barbie b = new Barbie("mydoll");
    }
}

Bu sual həm də “Order of Initialization” mövzusu ilə əlaqəlidir, kodu compile etməyə cəhd etsək görəcəyik ki, compiler bizə “cannot reference name before supertype constructor has been called” xətasını göstərəcək. Əgər line1-i commentdən çıxarsaq kod yenə compile olunmayacaq, çünki super constructor çağırılmamış name dəyişəninə dəyər mənimsədilmir.

 

[topics lang=az]

About the author

Mushfiq Mammadov

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.