Kategorie szkoleń | Egzaminy | Kontakt
  • 1
  • 2
  • 238
class ClassA {}

class ClassB extends ClassA {}

class ClassC extends ClassA {}

public class Test {
  public static void main(String args[]) throws Exception {
    ClassA p0 = new ClassA();
    ClassB p1 = new ClassB();
    ClassC p2 = new ClassC();
    ClassA p3 = new ClassB();
    ClassA p4 = new ClassC();
    p0 = p1;
    p1 = p2;
    p2 = p4;
    p2 = (ClassC)p1;
    p1 = (ClassB)p3;
    p2 = (ClassC)p4;
  }
}
Proszę o dokładne wytłumaczenie i przeanalizowanie dlaczego
p1 = p2;
p2 = p4;
p2 = (ClassC)p1;
są błędne. 

 

 

Sylwester_Dudkiewicz
  • Zapytał
  • @ Sylwester_Dudkiewicz | 07.02.2014
    • 11
    • 2
    • 2

Odpowiedź (1)

  • 9

W przykładzie mamy dwie klasy (ClassB oraz ClassC), które dziedziczą po klasie ClassA. Oznacza to, że przejmują one ich zachowanie. To zachowanie klasy potomne mogą pozostawić bez zmian, zmodyfikować lub rozszerzyć. Stąd każdy typ potomny "pasuje" do typu bazowego, bo oba posiadają wspólny zestaw metod. To jest powodem dla którego tego typu relację nazywamy relacją IS_A (obiekt typu potomnego jest także obiektem typu bazowego).

Polimorfizm umożliwia sformalizowanie tego podobieństwa poprzez zapis:

TypBazowy ref = new TypPotomny();

Każdy obiekt typu potomnego (podtypu) można wskazać poprzez referencję typu bazowego (nadtypu). Konwersja typów następuje tu automatycznie. W każdym innym przypadku, jeśli konwersję chcemy wymusić (na własną odpowiedzialność), to trzeba stosować rzutowanie. Niedozwolone rzutowanie może być wykryte przez kompilator lub spowodować wystąpienie wyjątku na etapie wykonania. Przykład ilustruje właśnie takie sytuacje.

Przyjrzyjmy się temu, co mamy w programie i przeanalizujmy krok po kroku kolejne przypisania:

Instrukcja:

p0 = p1;

oznacza, że za pomocą referencji p0 typu ClassA wskazujemy obiekt typu ClassB.  Klasa ClassB b po klasie ClassA, więc przypisanie jest prawidłowe - nastąpi automatyczna konwersja typu.

Instrukcja:

p1 = p2;

oznacza, że za pomocą referencji p1 typu ClassB wskazujemy obiekt typu ClassC.  Klasy ClassB oraz ClassC, nie są ze sobą w relacji dziedziczenia (żadna nie dziedziczy po drugiej), lecz mają tylko wspólnego przodka. Takie przypisanie jest nieprawidłowe i zostanie ono wykryte przez kompilator (błąd kompilacji). Nie można rzutować typów z dwóch różnych gałęzi hierarchii dziedziczenia.

Instrukcja:

p2 = p4;

oznacza, że za pomocą referencji p2 typu ClassC wskazujemy obiekt typu ClassA.  Klasa ClassC nie dziedziczy po klasie ClassA (tylko na odwrót), więc przypisanie nie jest prawidłowe. Kompilator zgłosi w takiej sytuacji błąd. Aby błędu nie było, konieczne byłoby rzutowanie: p2 = (ClassC)p4;

Instrukcja:

p2 = (ClassC)p1;

oznacza, że obiekt typu ClassB (wskazywany przez referencję p1) rzutujemy na typ ClassC i wskazujemy za pomocą referencji p2 typu ClassC. Rzutowanie typu ClassB na typ ClassC jest niedozwolone, bo te klasy nie są ze sobą w relacji dziedziczenia. W konsekwencji mamy błąd kompilacji.

Instrukcja:

p1 = (ClassB)p3;

oznacza, że obiekt typu ClassA (wskazywany przez referencję p3) rzutujemy na typ ClassB i wskazujemy za pomocą referencji p1 typu ClassB. Po obu stronach operatora przypisania mamy więc identyczne typy (ClassB). Kompilator zzakceptuje także rzutowanie typu ClassA na typ ClassB, bo są one w relacji dziedziczenia (ClassB rozszerza typ ClassA). W trakcie wykonania nie wystąpi wyjątek, gdyż faktycznie referencja p3 służy do wskazania obiektu typu ClassB, więc jej zrzutowanie na typ ClassB jest poprawne.

Instrukcja:

p2 = (ClassC)p4;

oznacza, że obiekt typu ClassA (wskazywany przez referencję p4) rzutujemy na typ ClassC i wskazujemy za pomocą referencji p2 typu ClassC. Po obu stronach operatora przypisania mamy więc identyczne typy (ClassC). Kompilator zzakceptuje także rzutowanie typu ClassA na typ ClassC, bo są one w relacji dziedziczenia (ClassC rozszerza typ ClassA). W trakcie wykonania nie wystąpi wyjątek, gdyż faktycznie referencja p4 służy do wskazania obiektu typu ClassC, więc jej zrzutowanie na typ ClassC jest poprawne.

  • Odpowiedział
  • @ | 08.02.2014
  • TRENER MODERATOR ALTKOM AKADEMII