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...

Strona główna