Funkcje wirtualne i klasy abstrakcyjne

Polimorfizm dynamiczny

Polimorfizm dynamiczny w większości języków programowania realizowany jest poprzez funkcje wirtualne i klasy abstrakcyjne.

Odnośniki w kontekście hierarchii dziedziczenia

Odnośnik (wskaźnik, referencja, obiekt typu referencyjnego) do pokazywania na obiekty klasy podstawowej może być wykorzystany do pokazywania na obiekty klasy pochodnej, a także na wszystkie obiekty w dół hierarchii dziedziczenia. Tak więc odnośnikiem do pokazywania na obiekty klasy Samochod można również pokazywać na obiekty klasy Taksowka, RadioTaxi jak i TaksowkaBagazowa. odnośnik do pokazywania na obiekty klasy podstawowej: może pokazywać na wszystkie obiekty w dół hierarchii dziedziczenia Animację mrugania obiektu klasy Klocek można zrealizować jako następującą metodę animacja mrugania obiektu klasy Klocek
public void mrugaj(int ileRazy){
  for(int i=0;i<ileRazy;i++){
    schowaj();
    delay(0.3);
    pokaz();
    delay(0.3);
  }
}

Funkcje wirtualne

Przykład w C#

Klasa Klocek

Klasa KlocekObramowany

Klasa Mrugacz

Wczesne i późne wiązanie

Polimorfizm dynamiczny realizowany przez funkcje wirtualne zostaje urzeczywistniony tylko tam, gdzie zachodzi późne wiązanie funkcji wirtualnej.

Polimorfizm dynamiczny ujawnia się tylko przy wywołaniach metod za pomocą odnośnika, a nie obiektu.

Jak to można zrobić?

Jak to można zrobić?

Jak to można zrobić?

Jak to można zrobić?

Jak to można zrobić?

Pożytki i koszty wirtualności

Podstawowym pożytkiem z wirtualnego wywołania funkcji jest możliwość tworzenia uniwersalnego kodu, który działa poprawnie bez żadnych modyfikacji na klasach pochodnych napisanych kiedykolwiek później. Za wirtualność się jednak płaci:

  • W C++ i C# mamy wybór: funkcję poprzedzamy słowem kluczowym virtual, jeśli chcemy, by funkcja była wirtualna.
  • W Javie tego słowa się nie używa, bo wszystkie funkcje automatycznie są wirtualne.

Wielokrotne wykorzystanie kodu

Wielokrotne wykorzystanie kodu

Klasa Mrugacz może wyglądać tak

class Mrugacz{
  ...
  int wiersz,kolumna;
  abstract void pokaz();
  abstract void schowaj();
  void mrugaj(){
     ...
  }
  ...
}

Idea klasy abstrakcyjnej

Dlaczego pasuje tu nazwa klasa abstrakcyjna? Bo nie wchodzimy w szczegóły jak figurę "pokazać" (jak działa funkcja pokaz) i jak ją "schować" (jak działa funkcja schowaj) - to zależy od konkretnej figury i to zrobimy dopiero w stosownych klasach pochodnych.

  • W C++ funkcję czynimy abstrakcyjną dopisując przed średnikiem kończącym jej deklarację znak równości oraz zero.
  • W C# i Javie funkcję czynimy abstrakcyjną poprzedzając jej deklarację słowem kluczowym abstract.
  • W C++ klasę czynimy abstrakcyjną umieszczając w niej funkcję abstrakcyjną
  • W C# i Javie dodatkowo również przed samą definicją klasy stawiamy słowo kluczowe abstract.

Przykłady w C#

Prezenty

Klasa Opadacz-abstrakcyjna

Klasa Klocek

Klasa Trojkat

Klasa Paczka

Klasa Prezenty

Szyfrant

Klasa Szyfrant

Stack

Klasa StackTest

Cechy klasy abstrakcyjnej

Budowanie na abstrakcji

void opusc(int wierszPodestu){
  while(wiersz<wierszPodestu){
    schowaj();
    wiersz+=1;
    pokaz();
    delay(0.01);
  }
}

Interfejsy

  • Język C++ nie wspiera pojęcia interfejsu od strony składniowej.
  • W C# i Javie informujemy kompilator, że tworzymy interfejs używając słowa kluczowego interface w miejsce słowa kluczowego class.
  • Ponadto w Javie przy dziedziczeniu klasy po interfejsie używamy słowa kluczowego implements w miejsce extends.

Istota programowania obiektowo orientowanego

Programowanie obiektowe w literaturze angielskojęzycznej dzieli się na dwa szczeble

dwa szczeble programowania obiektowego

Jest między tymi technikami bardzo istotna różnica, którą terminologia, szczególnie nieugruntowana terminologia polska bardzo zaciera.