Java. Спадковість. Посилання на об’єкт підкласу. Виклик конструктора суперкласу. Ключове слово super

Спадковість. Посилання на об’єкт підкласу. Виклик конструктора суперкласу. Ключове слово super


Зміст



1. Чи можна посиланню на суперклас присвоїти посилання на об’єкт підкласу?

Так, можна. Нехай дано суперклас та підклас. Якщо оголосити посилання на суперклас, то цьому посиланню можна присвоїти значення посилання на підклас, що успадковує цей суперклас.

Наприклад. Дано класи A та B. Клас A є суперкласом (базовим класом). Клас B є підкласом класу A.

// клас A - суперклас для класу B
class A {
    int a; // внутрішня змінна
}

// клас B - підклас класу A
class B extends A {
    int b;
}

Тоді, в іншому методі можна оголосити посилання на клас A і присвоїти цьому посиланню значення екземпляру класу B

// посилання на клас A може посилатись на клас B
A objA = new A(); // екземпляр (об'єкт) класу A
B objB = new B(); // екземпляр (об'єкт) класу B
A rA; // посилання на клас A

// посиланню на клас A присвоюється посилання на екземпляр класу B
rA = objB;

rA.a = 30; // так можна, rA.a = 30
// rA.b = 20; // помилка, заборонено
rA = objA; // так теж можна, однак rA.a = 0

У випадку присвоювання посиланню на суперклас rA посилання на об’єкт підкласу objB доступними для посилання rA є члени класу A, для якого було оголошено це посилання. У даному випадку посиланню rA доступний член класу A з іменем a. Члени класу B є недоступними для посилання rA.

Висновок: для посилання на суперклас доступні члени класу визначаються типом посилання, а не типом об’єкту на який це посилання посилається.

Якщо за допомогою посилання rA спробувати доступитись до члену даних b класу B

rA.b = 20;

то компілятор видасть помилку

b cannot be resolved or is not a field

 

2. Чи можна посиланню на підклас присвоїти посилання на об’єкт суперкласу?

Ні, не можна. Суперклас не може розширюватись до можливостей підкласу. Це суперечить парадигмі спадковості. Навпаки, підклас, який розширює можливості суперкласу, може “звужуватись” до суперкласу.

Наприклад. Нехай задано два класи A та B. Клас A є суперкласом (базовим класом). Клас B є підкласом класу A.

// клас A - суперклас для класу B
class A {
    int a; // внутрішня змінна
}

// клас B - підклас класу A
class B extends A {
    int b;
}

Спроба присвоїти посиланню на клас B значення посилання на клас A

A objA = new A(); // objA - посилання на екземпляр класу A
B rB; // посилання на підклас B

// суперклас A не може бути приведений до класу B
rB = (B)objA; // помилка!

призведе до виникнення критичної ситуації з повідомленням

A cannot be cast to B

 

3. Які існують форми використання ключового слова super?

Існують дві форми використання ключового слова super:

  • для виклику конструктора суперкласу;
  • для доступу до члена суперкласу з підкласу. Такий доступ потрібен в ситуаціях, коли ім’я члена підкласу співпадає з іменем члена суперкласу, до якого потрібно доступитись з підкласу. У цьому випадку ім’я члену даних підкласу перекриває ім’я суперкласу.

 

4. Як здійснюється виклик з підкласу конструктора суперкласу? Ключове слово super. Загальна форма

Конструктор суперкласу (базового класу) може бути викликаний з підкласу (похідного класу). Цей виклик здійснюється з допомогою ключового слова super. Виклик конструктора суперкласу повинен бути здійснений в тілі конструктора підкласу першим.

Загальна форма виклику конструктора суперкласу з конструктора підкласу наступна:

super(parameters);

тут

  • parameters – перелік параметрів, які отримує конструктор. Якщо конструктор немає параметрів, то конструктор суперкласу викликається як super().

 

5. Приклади виклику конструкторів суперкласу з підкласу

Приклад 1. Задано клас Point, який описує точку на площині. Клас розширюється підкласом ColorPoint, який додає властивість колір до точки.

Реалізація класів Point та ColorPoint наступна

// клас, що описує точку на площині
class Point {
    // координати точки
    private double x;
    private double y;

    // конструктор класу
    public Point() {
        x = y = 0;
    }

    public Point(double _x, double _y) {
        x = _x;
        y = _y;
    }

    // методи доступу
    // взяти точку
    public Point GetP() {
        return this;
    }

    // встановити нове значення точки
    public void SetP(Point np) {
        x = np.x;
        y = np.y;
    }

    public double GetX() { return x; }
    public double GetY() { return y; }
}

// клас точка з кольором - розширює можливості Point
class ColorPoint extends Point {
    private double color;

    // конструктори класу ColorPoint
    ColorPoint() {
        // викликати конструктор без параметрів суперкласу Point
        super();
        color = 0;
    }

    ColorPoint(double _x, double _y, double _c) {
        // викликати конструктор з двома параметрами класу Point
        super(_x,_y);
        color = _c;
    }

    // встановити нове значення ColorPoint
    void SetCP(double _x, double _y, double _c) {
        // super(_x,_y); // заборонено викликати конструктор з методу
        Point p = new Point(_x,_y); // створити об'єкт класу Point
        SetP(p); // встановити нове значення координат точки
        color = _c;
    }

    // зчитати колір
    public double GetColor() {
        return color;
    }
}

У вищенаведеному коді, в конструкторах підкласу ColorPoint викликається конструктор класу Point з допомогою ключового слова super

...

// конструктори класу ColorPoint
ColorPoint() {
    // викликати конструктор без параметрів суперкласу Point
    super();
    color = 0;
}

ColorPoint(double _x, double _y, double _c) {
    // викликати конструктор з двома параметрами класу Point
    super(_x,_y);
    color = _c;
}

...

Приклад 2. Виклик конструктора суперкласу у випадку багаторівневої спадковості. У прикладі оголошується 4 класи з іменами A1, A2, A3, A4. Клас A1 є суперкласом для класу A2. Клас A2 є суперкласом для класу A3. Клас A3 є суперкласом для класу A4.

Нижче наведено програмний код, що демонструє використання ключового слова super та багаторівневої спадковості

// суперклас
class A1 {
    A1() {
        System.out.println("A1");
    }
}

// підклас класу A1
class A2 extends A1 {
    A2() {
        super();
        System.out.println("A2");
    }
}

// підклас класу A2
class A3 extends A2 {
    A3() {
        super();
        System.out.println("A3");
    }
}

// підклас класу A3
class A4 extends A3 {
    A4() {
        super();
        System.out.println("A4");
    }
}

Якщо створити екземпляр класу A4

A4 objA4 = new A4();

то буде виведено наступний результат

A1
A2
A3
A4

У вищенаведеному прикладі клас A2 успадковує усі характеристики класу A1. Клас A3 успадковує усі характеристики класів A1, A2. Клас A4 успадковує усі характеристики класів A1, A2, A3.

 

6. Які вимоги ставляться до виклику конструктора суперкласу з допомогою ключового слова super?

До виклику конструктора суперкласу з допомогою ключового слова super ставляться наступні вимоги:

  • конструктор суперкласу може бути викликаний тільки з конструктора підкласу;
  • виклик констуктора суперкласу має бути першим в конструкторі підкласу;
  • викликати конструктор суперкласу з будь-якого методу підкласу (крім конструктора) заборонено.

 

7. Чи можна викликати конструктор суперкласу з будь-якого методу підкласу з допомогою виклику super?

Ні, не можна. Якщо в деякому методі підкласу спробувати викликати конструктор суперкласу з допомогою ключового слова super(), то компілятор Java видасть помилку:

Constructor call must be the first statement in a constructor

 

8. Приклад доступу до члена суперкласу з підкласу з використанням ключового слова super

Ключове слово super використовується для доступу до члена суперкласу у випадку, коли в підкласі використовується таке саме ім’я.

// доступ до члена суперкласу з допомогою слова super
class A {
    double x = 2.5;
}

class B extends A {
    double x = 5.0; // змінна x класу A
}

class C extends B {
    double x = super.x; // x = 5.0 - змінна x класу B
}

У вищенаведеному прикладі член x класу C ініціалізується значенням x класу B з допомогою звернення:

super.x

 

9. Яким чином здійснюється порядок виклику конструкторів у випадку успадкування? Приклад

Якщо два і більше класів утворюють ієрархію успадкування, то конструктори викликаються в напрямку від найвищого класу в ієрархії (від суперкласу) до найнижчого (до підкласу найнижчого рівня).

Наприклад. Задано 4 класи з іменами A, B, C, D. Клас A є суперкласом для класу B. Клас B є суперкласом для класу C. Клас C є суперкласом для класу D.

// клас A - найвищий клас в ієрархії
class A {
    // конструктор класу A
    A() {
        System.out.println("The constructor of class A.");
    }
}

// клас B є підкласом класу A
class B extends A {
    // конструктор класу B
    B() {
        System.out.println("The constructor of class B.");
    }
}

//клас C є підкласом класу B
class C extends B {
    // конструктор класу C
    C() {
        System.out.println("The constructor of class C.");
    }
}

//клас D є підкласом класу C
class D extends C {
    // конструктор класу D
    D() {
        System.out.println("The constructor of class D.");
    }
}

public class Train01 {
    public static void main(String[] args) {

        // створити об'єкт класу D
        D objD = new D(); // конструктори викликаюься в порядку A(), B(), C(), D()
    }

}

У вищенаведеному прикладі при оголошенні об’єкту класу D

D objD = new D(); // конструктори викликаюься в порядку A(), B(), C(), D()

конструктори викликаються в порядку

A()
B()
C()
D()

Результат виконання програми

The constructor of class A.
The constructor of class B.
The constructor of class C.
The constructor of class D.

 


Зв’язані теми