Dziedziczenie
/* Test1.java */
// dziedziczenie
// Klasa potomna Dziecko dziedziczy zmienne i metody z klasy
// bazowej Rodzic. Zmienne i metody z modyfikatorem private
// nie są dziedziczone. Konstruktory nie są dziedziczone.
// Wszystkie klasy albo pośrednio albo bezpośrednio dziedziczą
// po klasie Object. Klasa Dziecko dziedziczy po klasie Object
// przez klasę Rodzic, a klasa Rodzic dziedziczy bezpośrednio.
// Klasa dziedziczy również klasy zagnieżdżone (ang. inner classes),
// klasy wewnętrzne (ang. nested classes) i interfejsy wewnętrzne
// (ang. nested interfaces) z klasy bazowej. Inicjalizery statyczne
// i obiektowe nie są dziedziczone.
class Rodzic
{
int a = 0;
static int b = 1;
void metodaObiektowa()
{
System.out.println("Metoda obiektowa klasy Rodzic.");
}
static void metodaStatyczna()
{
System.out.println("Metoda statyczna klasy Rodzic.");
}
}
class Dziecko extends Rodzic
{
}
public class Test1
{
public static void main(String[] args)
{
Dziecko kid = new Dziecko();
System.out.println("a = " + kid.a);
System.out.println("b = " + kid.b);
kid.metodaObiektowa();
Dziecko.metodaStatyczna();
}
}
a = 0
b = 1
Metoda obiektowa klasy Rodzic.
Metoda statyczna klasy Rodzic.
Press any key to continue...
/* Test2.java */
// dziedziczenie + definiowanie nowych metod i zmiennych w klasie potomnej
// Klasa potomna Dziecko może określać własne zmienne i metody.
class Rodzic
{
int a = 0;
static int b = 1;
void metodaObiektowa()
{
System.out.println("Metoda obiektowa klasy Rodzic.");
}
static void metodaStatyczna()
{
System.out.println("Metoda statyczna klasy Rodzic.");
}
}
class Dziecko extends Rodzic
{
int c = 3;
static int d = 4;
void mObiektowa()
{
System.out.println("Metoda obiektowa klasy Dziecko.");
}
static void mStatyczna()
{
System.out.println("Metoda statyczna klasy Dziecko.");
}
}
public class Test2
{
public static void main(String[] args)
{
Dziecko kid = new Dziecko();
System.out.println("a = " + kid.a);
System.out.println("b = " + kid.b);
kid.metodaObiektowa();
Dziecko.metodaStatyczna();
System.out.println("c = " + kid.c);
System.out.println("d = " + kid.d);
kid.mObiektowa();
Dziecko.mStatyczna();
}
}
a = 0
b = 1
Metoda obiektowa klasy Rodzic.
Metoda statyczna klasy Rodzic.
c = 3
d = 4
Metoda obiektowa klasy Dziecko.
Metoda statyczna klasy Dziecko.
Press any key to continue...
/* Test3.java */
// przesłanianie metod obiektowych
// Jeśli w klasie potomnej umieścimy metodę obiektową,
// która ma taką samą sygnaturę i typ wartości zwracanej
// co metoda obiektowa z klasy bazowej, to metoda z klasy
// potomnej przesłoni (ang. override) metodę z klasy bazowej.
// Metody przesłonięte nie są dziedziczone do klasy potomnej.
// Metoda z klasy potomnej, która przesłania metodę z klasy
// bazowej nie może osłabiać jej modyfikatora dostępu.
// Klasa obiektu, czyli inaczej typ obiektu
// określony jest przez nazwę konstruktora.
// Polimorfizm:
// Referencja do obiektu klasy potomnej może mieć
// typ klasy potomnej albo typ dowolnej klasy bazowej,
// po której dziedziczy klasa potomna.
// Przez referencję typu klasy bazowej można odwołać
// się jedynie do zmiennych i metod określonych w klasie
// bazowej, dlatego niekiedy zachodzi potrzeba zrzutowania
// referencji typu klasy bazowej do typu klasy potomnej.
// Jeśli metoda obiektowa z klasy potomnej przesłania
// metodę obiektową z klasy bazowej, to niezależnie
// od typu referencji do obiektu klasy potomnej, przy
// wywołaniu tej metody na rzecz obiektu klasy potomnej,
// zawsze nastąpi wywołanie metody z klasy potomnej.
// Innymi słowy, o tym, jaka metoda obiektowa zostanie
// wywołana na rzecz danego obiektu decyduje typ obiektu
// a nie typ referencji do obiektu.
class Rodzic
{
public void metodaObiektowa()
{
System.out.println("Metoda obiektowa klasy Rodzic.");
}
}
class Dziecko extends Rodzic
{
public void metodaObiektowa()
{
System.out.println("Metoda obiektowa klasy Dziecko.");
}
}
public class Test3
{
public static void main(String[] args)
{
Dziecko kid1 = new Dziecko();
Rodzic kid2 = new Dziecko();
Object kid3 = new Dziecko();
kid1.metodaObiektowa();
kid2.metodaObiektowa();
((Dziecko)kid3).metodaObiektowa();
((Rodzic)kid3).metodaObiektowa();
// Poza klasą Dziecko, na rzecz obiektu klasy Dziecko nie można
// wywołać przesłoniętej metody obiektowej z klasy bazowej Rodzic.
}
}
Metoda obiektowa klasy Dziecko.
Metoda obiektowa klasy Dziecko.
Metoda obiektowa klasy Dziecko.
Metoda obiektowa klasy Dziecko.
Press any key to continue...
/* Test4.java */
// wywołanie z metody obiektowej klasy potomnej
// metody przesłoniętej z klasy nadrzędnej
// Metoda obiektowa z klasy potomnej może wywołać
// metodę przesłoniętą z klasy nadrzędnej przy
// pomocy słowa kluczowego super.
class Rodzic
{
void metodaObiektowa()
{
System.out.println("Metoda obiektowa klasy Rodzic.");
}
}
class Dziecko extends Rodzic
{
void metodaObiektowa()
{
System.out.println("Metoda obiektowa klasy Dziecko.");
super.metodaObiektowa();
}
}
public class Test4
{
public static void main(String[] args)
{
Dziecko kid = new Dziecko();
kid.metodaObiektowa();
}
}
Metoda obiektowa klasy Dziecko.
Metoda obiektowa klasy Rodzic.
Press any key to continue...
/* Test5.java */
// wywołanie z klasy potomnej konstruktora z klasy bazowej
// Aby poprawnie zainicjować obiekt klasy potomnej, konstruktor
// z klasy potomnej zawsze wywołuje konstruktor z klasy bazowej.
// Wywołanie konstruktora z klasy bazowej ma postać super(parametry).
// Słowo kluczowe super(parametry) musi być pierwszą instrukcją
// w ciele konstruktora klasy potomnej. Jeśli wywołanie konstruktora
// klasy bazowej nie zostanie podane jawnie, to kompilator wstawi
// wywołanie domyślne, które ma postać super().
class Rodzic
{
Rodzic()
{
System.out.println("Rodzic()");
}
}
class Dziecko extends Rodzic
{
Dziecko()
{
// super(); // domyślne wywołanie konstruktora z klasy bazowej
System.out.println("Dziecko()");
}
}
public class Test5
{
public static void main(String[] args)
{
Dziecko kid = new Dziecko();
}
}
Rodzic()
Dziecko()
Press any key to continue...
/* Test6.java */
// jawne wywołanie z klasy potomnej konstruktora z klasy bazowej
// Zmienne odziedziczone z klasy bazowej do klasy potomnej
// są inicjowane przez konstruktor z klasy bazowej.
class Rodzic
{
int a;
Rodzic(int a)
{
this.a = a;
}
}
class Dziecko extends Rodzic
{
int b;
Dziecko(int a, int b)
{
super(a);
this.b = b;
}
}
public class Test6
{
public static void main(String[] args)
{
Rodzic dad = new Rodzic(1);
Dziecko kid = new Dziecko(2,3);
System.out.println("Obiekt klasy Rodzic, a = " + dad.a);
System.out.println("Obiekt klasy Dziecko, a = " + kid.a + ", b = " + kid.b);
}
}
Obiekt klasy Rodzic, a = 1
Obiekt klasy Dziecko, a = 2, b = 3
Press any key to continue...
/* Test7.java */
// inicjowanie obiektów klasy potomnej
// 1. Zmienne obiektowe przyjmują wartości "zerowe".
// 2. Wywoływany jest konstruktor z klasy bazowej.
// 3. Określane są wartości zmiennych obiektowych.
// 4. Wykonywane jest ciało konstruktora klasy potomnej.
// Jeśli konstruktor obiektu klasy potomnej wywołuje
// konstruktor z klasy bazowej, a konstruktor z klasy
// bazowej odwołuje się do metody obiektowej, która
// została przesłonięta przez metodę obiektową z klasy
// potomnej, to w takim przypadku konstruktor z klasy
// bazowej wywoła metodę obiektową z klasy potomnej.
class Rodzic
{
int a = 1;
void info()
{
System.out.println("Metoda obiektowa klasy Rodzic.");
System.out.println("a = " + a);
}
Rodzic()
{
info();
}
}
class Dziecko extends Rodzic
{
int a = 2;
void info()
{
System.out.println("Metoda obiektowa klasy Dziecko.");
System.out.println("a = " + a);
}
Dziecko()
{
// 1. Zmienne obiektowe przyjmują wartości "zerowe".
// 2. Wywoływany jest konstruktor z klasy bazowej. // super()
// 3. Określane są wartości zmiennych obiektowych.
info(); // 4. Wykonywane jest ciało konstruktora.
}
}
public class Test7
{
public static void main(String[] args)
{
new Dziecko();
}
}
Metoda obiektowa klasy Dziecko.
a = 0
Metoda obiektowa klasy Dziecko.
a = 2
Press any key to continue...
/* Test8.java */
// przesłanianie metod statycznych
// Jeśli w klasie potomnej umieścimy metodę statyczną,
// która ma taką samą sygnaturę i typ wartości zwracanej
// co metoda statyczna z klasy bazowej, to metoda z klasy
// potomnej przesłoni (ang. hide) metodę z klasy bazowej.
// Metody przesłonięte nie są dziedziczone do klasy potomnej.
// Metoda z klasy potomnej, która przesłania metodę z klasy
// bazowej nie może osłabiać jej modyfikatora dostępu.
// Klasa obiektu, czyli inaczej typ obiektu
// określony jest przez nazwę konstruktora.
// Polimorfizm:
// Referencja do obiektu klasy potomnej może mieć
// typ klasy potomnej albo typ dowolnej klasy bazowej,
// po której dziedziczy klasa potomna.
// Jeśli metoda statyczna z klasy potomnej przesłania
// metodę statyczną z klasy bazowej, to przy wywołaniu
// tej metody przez referencję do obiektu klasy potomnej,
// zawsze zostanie wywołana metoda statyczna z tej klasy,
// która określa typ referencji do obiektu klasy potomnej.
// Innymi słowy, o tym, jaka metoda statyczna zostanie
// wywołana przez referencję do danego obiektu decyduje
// typ referencji a nie typ obiektu.
class Rodzic
{
public static void metodaStatyczna()
{
System.out.println("Metoda statyczna klasy Rodzic.");
}
}
class Dziecko extends Rodzic
{
public static void metodaStatyczna()
{
System.out.println("Metoda statyczna klasy Dziecko.");
}
}
public class Test8
{
public static void main(String[] args)
{
Dziecko kid1 = new Dziecko();
Rodzic kid2 = new Dziecko();
Object kid3 = new Dziecko();
kid1.metodaStatyczna();
kid2.metodaStatyczna();
((Dziecko)kid3).metodaStatyczna();
((Rodzic)kid3).metodaStatyczna();
}
}
Metoda statyczna klasy Dziecko.
Metoda statyczna klasy Rodzic.
Metoda statyczna klasy Dziecko.
Metoda statyczna klasy Rodzic.
Press any key to continue...
/* Test9.java */
// wywołanie z metody statycznej klasy potomnej
// metody przesłoniętej z klasy nadrzędnej
// W zawartości statycznej nie możemy używać słowa
// kluczowego super i this. Metodę statyczną z klasy
// nadrzędnej musimy wywołać przez nazwę klasy.
class Rodzic
{
public static void metodaStatyczna()
{
System.out.println("Metoda statyczna klasy Rodzic.");
}
}
class Dziecko extends Rodzic
{
public static void metodaStatyczna()
{
System.out.println("Metoda statyczna klasy Dziecko.");
Rodzic.metodaStatyczna();
}
}
public class Test9
{
public static void main(String[] args)
{
Dziecko kid = new Dziecko();
kid.metodaStatyczna();
}
}
Metoda statyczna klasy Dziecko.
Metoda statyczna klasy Rodzic.
Press any key to continue...
/* Test10.java */
// wywołanie z metody obiektowej klasy potomnej
// metody statycznej z klasy nadrzędnej
// Metoda obiektowa z klasy potomnej może wywołać
// metodę statyczną z klasy nadrzędnej przy pomocy
// słowa kluczowego super i this. Aby wywołać metodę
// statyczną z klasy nadrzędnej przy pomocy referencji
// this, musimy typ tej referencji zrzutować do typu
// klasy nadrzędnej.
class Rodzic
{
static void metodaStatyczna()
{
System.out.println("Metoda statyczna klasy Rodzic.");
}
}
class Dziecko extends Rodzic
{
void metodaObiektowa()
{
System.out.println("Metoda obiektowa klasy Dziecko.");
Rodzic.metodaStatyczna();
super.metodaStatyczna();
((Rodzic)this).metodaStatyczna();
}
}
public class Test10
{
public static void main(String[] args)
{
Dziecko kid = new Dziecko();
kid.metodaObiektowa();
}
}
Metoda obiektowa klasy Dziecko.
Metoda statyczna klasy Rodzic.
Metoda statyczna klasy Rodzic.
Metoda statyczna klasy Rodzic.
Press any key to continue...
/* Test11.java */
// przesłanianie zmiennych obiektowych
// Jeśli w klasie potomnej umieścimy zmienną obiektową,
// która ma taką samą nazwę co zmienna obiektowa z klasy
// bazowej, to zmienna z klasy potomnej przesłoni (ang.hide)
// zmienną z klasy bazowej. Zmienne przesłonięte nie są
// dziedziczone, ale mimo to są implementowane w obiektach
// klasy potomnej.
// Jeśli zmienna obiektowa z klasy potomnej przesłania
// zmienną obiektową z klasy bazowej, to przy odwołaniu
// do tej zmiennej przez referencję do obiektu klasy
// potomnej, nastąpi odwołanie do zmiennej obiektowej
// zadeklarowanej w tej klasie, która określa typ
// referencji do obiektu klasy potomnej.
// Innymi słowy, o tym, do jakiej zmiennej obiektowej
// uzyskamy dostęp przez referencję do danego obiektu
// decyduje typ referencji a nie typ obiektu.
class Rodzic
{
double a = 1.0;
}
class Dziecko extends Rodzic
{
int a = 2;
}
public class Test11
{
public static void main(String[] args)
{
Dziecko kid1 = new Dziecko();
Rodzic kid2 = new Dziecko();
System.out.println("kid1 ma typ Dziecko, a = " + kid1.a);
System.out.println("kid2 ma typ Rodzic, a = " + kid2.a);
}
}
kid1 ma typ Dziecko, a = 2
kid2 ma typ Rodzic, a = 1.0
Press any key to continue...
/* Test12.java */
// przesłanianie zmiennych statycznych
// Jeśli zmienna statyczna z klasy potomnej przesłania
// zmienną statyczną z klasy bazowej, to przy odwołaniu
// do tej zmiennej przez referencję do obiektu klasy
// potomnej, nastąpi odwołanie do zmiennej statycznej
// z tej klasy, która określa typ referencji do obiektu
// klasy potomnej.
// Innymi słowy, o tym, do jakiej zmiennej statycznej
// uzyskamy dostęp przez referencję do danego obiektu
// decyduje typ referencji a nie typ obiektu.
class Rodzic
{
static double a = 1.0;
}
class Dziecko extends Rodzic
{
static int a = 2;
}
public class Test12
{
public static void main(String[] args)
{
Dziecko kid1 = new Dziecko();
Rodzic kid2 = new Dziecko();
System.out.println("kid1 ma typ Dziecko, a = " + kid1.a);
System.out.println("kid2 ma typ Rodzic, a = " + kid2.a);
}
}
kid1 ma typ Dziecko, a = 2
kid2 ma typ Rodzic, a = 1.0
Press any key to continue...
/* Test13.java */
// odwołanie z metody obiektowej klasy potomnej
// do zmiennych przesłoniętych z klasy bazowej
// Metoda obiektowa z klasy potomnej może odwołać się
// do zmiennych przesłoniętych z klasy bazowej przy
// pomocy słowa kluczowego super i this. Aby odwołać
// się do zmiennych przesłoniętych z klasy bazowej
// przy pomocy referencji this, musimy typ tej
// referencji zrzutować do typu klasy bazowej.
class Rodzic
{
int a = 1;
static int b = 2;
}
class Dziecko extends Rodzic
{
int a = 3;
static int b = 4;
void metodaObiektowa()
{
System.out.println("Metoda obiektowa klasy Dziecko.");
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("Zmienne przesloniete:");
System.out.println("a = " + super.a);
System.out.println("a = " + ((Rodzic)this).a);
System.out.println("b = " + super.b);
System.out.println("b = " + Rodzic.b);
System.out.println("b = " + ((Rodzic)this).b);
}
}
public class Test13
{
public static void main(String[] args)
{
Dziecko kid = new Dziecko();
kid.metodaObiektowa();
}
}
Metoda obiektowa klasy Dziecko.
a = 3
b = 4
Zmienne przesloniete:
a = 1
a = 1
b = 2
b = 2
b = 2
Press any key to continue...
/* Test14.java */
// odwołanie z metody statycznej klasy potomnej
// do zmiennej przesłoniętej z klasy nadrzędnej
// Zmienne statyczne nie mają dostępu do zawartości
// obiektowej klasy nadrzędnej. W zawartości statycznej
// nie możemy też użyć słowa kluczowego super i this.
// Z metody statycznej klasy potomnej do zmiennej
// przesłoniętej z klasy nadrzędnej musimy się
// odwołać przez nazwę klasy.
class Rodzic
{
int a = 1;
static int b = 2;
}
class Dziecko extends Rodzic
{
int a = 3;
static int b = 4;
static void metodaStatyczna()
{
System.out.println("Metoda statyczna klasy Dziecko.");
System.out.println("b = " + b);
System.out.println("Zmienne przesloniete:");
System.out.println("b = " + Rodzic.b);
}
}
public class Test14
{
public static void main(String[] args)
{
Dziecko.metodaStatyczna();
}
}
Metoda statyczna klasy Dziecko.
b = 4
Zmienne przesloniete:
b = 2
Press any key to continue...