Zaklinacz Żółwii

Start
Download
PJWSTK
ASD     
PRG     
SKO     
WPR     
GaduGadu
Humor
Alt Info

Funkcje wirtualne

Rozważmy następującą sytuację: chcemy zrobić ZOO, w którym bedą przechowywane różne zwierzaki. Oczywiście nie będziemy tworzyć osobnych zmiennych dla każdego zwierzaka, zwłaszcza, jeśli nie wiemy ile ich ma być (bo liczba może się zmieniać). Można użyć tablicy, jednak należy pamiętać, że może ona zawierać jedynie elementy takiego samego typu. Naszczęście znamy już dziedziczenie, więc chyba nie ma większego problemu. Tworzymy tablicę elementów typu Zwierzak (patrz poprzedni rozdział) a ponieważ "Pies", "Kot", "Żółw" i "Małpa" dziedziczą z klasy "Zwierzak" toteż do tablicy możemy wstawiać je wszystkie.

    HEH, ale proste! Ale ktoś chce, aby każdy zwieżak zawierał metodę dajGlos() i żeby ta metoda oczywiście działała inaczej dla psa inaczej dla kota, itd. Powiesz, że wystarczy umieścić w klasie (Pies, Kot, Żółw i Małpa) metodę dajGlos() i w każdej klasie dać inną definicję tej metody. To się oczywiście zgadza, ale jest jeden mały problem. Mamy tablicę elementów typu Zwierzak - klasa "Zwierzak" nie posiada metody daj głos, więc nie będziemy mieli jak wywołać takiej metody. Jeśli natomiast umieścimy metodę dajGlos() w klasie "Zwierzak" to zawsze będzie wywoływana taka sama metoda dawania głosu (z klasy "Zwierzak").

 +-----------+         +---------+          // Tu każdy zwierzak ma swoją metodę dajGlos()
 |Zwierzak   | --+---> |Pies     |
 +-----------+   |     +---------+          // ale jeśli mamy tablicę: Zwierzak tab[xxx]
 |           |   |     |dajGlos()|          // czyli elemty typu zwierzak
 +-----------+   |     +---------+          // to nie mamy im jak wydać polecenia dajGlos()
                 |
                 |     +---------+          // klasa Zwierzak nie ma takiej metody
                 +---> |Kot      |
                 |     +---------+
                 |     |dajGlos()|
                 |     +---------+
                 |
                 |     +---------+
                 +---> |Żółw     |
                 |     +---------+
                 |     |dajGlos()|
                 |     +---------+
                 |
                 |     +---------+
                 +---> |Małpa    |
                       +---------+
                       |dajGlos()|
                       +---------+
  Strony uczelniane:
   Str. Główna
   SerwisStudencki
   Poczta
   Sekret
   BSS-HOWTO
   Hasło
   Biblioteka
   Index stron
 

I tu właśnie nadszedł czas na wprowadzenie metod wirtualnych.
Umieszczamy metody 'dajGlos()' w każdej klasie 'Pies', 'Kot', itd. I definiujemy dla każdego zwierzsaka w taki sposób w jaki chcemy żeby dawał głos. Dodatkowo umieszczamy metodę 'dajGlos()' również w klasie 'Zwierzak', ale nie definiujemy jej - zostawiamy ją zupełnie pustą. Metoda ta nie będzie nic robić poza tym, że będzie istnieć. To, że metoda istnieje, powoduje, że możemy wydać polecenie 'dajGlos()' obiektom klasy 'Zwierzak'.
No i teraz UWAGA:
Mamy wskaźnik do objektów typu 'Zwierzak'.
Możemy mu wydać polecenie 'dajGlos()'.
Normalnie została by wywołana metoda 'dajGlos' klasy 'Zwierzak' (bo taki mamy wskaźnik)
Jednak my zadeklarujemy metodę 'dajGlos()' jako wirtualną
Przez co, wywołana zostanie metoda 'dajGlos()' takiego obiektu, na jaki wskazujemy.
Jeśli wskazujemy na psa, zostanie wywołana metoda z klasy 'Pies'
Jeśli wskazujemy na kota, zostanie wywołana metoda z klasy 'Kot'

I to jest ogólnie idea metod wirtualnych.
Wywołują one metodę nie z klasy jakiej jest wskaźnik (u nas klasy 'Zwierzak'), lecz z klasy jakiej jest obiekt który wskazujemy (np. 'Pies', 'Kot'...)