Poznámky
Osnova
Objektovo- Orientované Programovanie
Zapúzdrenie
Dedičnosť
Polymorfizmus
Trieda TKruh a TStvorec
  var g:TCanvas;
  type TKruh = class
         private
  x,y,r:integer; f:TColor; vid:boolean;
         public
         constructor Create(xx,yy,rr:integer);
         procedure ukaz;
         procedure skry;
         procedure ZmenFarbu(ff:TColor);
         procedure posun(dx,dy:integer);
  end;
OOP - polymorfizmus
Constructor TKruh.Create(xx,yy,rr:integer);
begin
    x:=xx;  y:=yy;  r:=rr;  vid:=false;  f:=clBlack;
end;
procedure TKruh.ukaz;
begin
    g.Pen.Color:=f;  g.Brush.Style:=bsClear; g.Ellipse(x-r,y-r,x+r,y+r);  vid:=true;
end;
OOP - polymorfizmus
procedure TKruh.skry;
begin
    g.Pen.Color:=clWhite;
    g.Brush.Style:=bsClear;
    g.Ellipse(x-r,y-r,x+r,y+r);    vid:=false;
end;
procedure TKruh.ZmenFarbu(ff:TColor);
begin
    f:=ff; if vid then ukaz;
end;
OOP - polymorfizmus
procedure TKruh.posun(dx,dy:integer);
var b:boolean;
begin
     b:=vid; if vid then skry;
     inc(x,dx); inc(y,dy);
     if b then ukaz;
end;
OOP - polymorfizmus, použitie
var a,b,c:TKruh;
      poc:integer;
procedure TForm1.FormCreate(Sender:TObject);
begin
      g:=Image1.Canvas;
end;
OOP - polymorfizmus, použitie
procedure TForm1.Button1Click(Sender:TObject);
     begin
         a:=TKruh.Create(100,100,50);
         with a do
         begin ZmenFarbu(clGreen);
                   ukaz;
         end;
     end;
OOP - polymorfizmus, použitie
procedure TForm1.Button2Click(Sender:TObject);
begin b:=TKruh.Create(300,200,100);
          b.ZmenFarbu(clRed);  b.ukaz;
end;
procedure TForm1.Button3Click(Sender:TObject);
begin
       c:=TKruh.Create(200,250,70); c.ukaz;
end;
OOP - polymorfizmus, použitie
procedure TForm1.Button4Click(Sender:TObject);
begin
      poc:=100; Timer1.Enabled:=true;
end;
procedure TForm1.Timer1Timer(Sender:TObject);
begin if a<>nil then a.posun(3,2);
          if b<>nil then b.posun(-5,-1);
          if c<>nil then c.posun(2,-3); dec(poc);
          if poc<=0 then Timer1.Enabled:=false;
end;
OOP - polymorfizmus, použitie
procedure  TForm1.Button5Click(Sender:TObject);
begin if a<>nil then with a do
             begin  if vid then skry; Free; a:=nil; end;
          if b<>nil then with b do
             begin  if vid then skry; Free; b:=nil; end;
          if c<>nil then with c do
             begin if vid then skry; Free; c:=nil; end;
end;

dodefinujeme novú triedu TStvorec - podtriedu TKruh
type TStvorec = class(TKruh)
    public
         procedure ukaz;
         procedure skry;
         procedure ZmenFarbu(ff:TColor);
         procedure posun(dx,dy:integer);
end;
OOP
procedure TStvorec.ukaz;
begin
    g.Pen.Color:=f;
    g.Brush.Style:=bsClear;
    g.Rectangle(x-r,y-r,x+r,y+r);  vid:=true;
end;
procedure TStvorec.skry;
begin
    g.Pen.Color:=clWhite;
    g.Brush.Style:=bsClear;
    g.Rectangle(x-r,y-r,x+r,y+r);  vid:=false;
end;
"procedure TStvorec.ZmenFarbu(ff:TColor..."
procedure TStvorec.ZmenFarbu(ff:TColor);
begin
         f:=ff; if vid then ukaz;
end;
procedure TStvorec.posun(dx,dy:integer);
var b:boolean;
begin b:=vid; if vid then skry;
          inc(x,dx);   inc(y,dy);
          if b then ukaz;
end;
"ak porovnáme metódy ZmenFarbu a..."
ak porovnáme metódy ZmenFarbu a posun v oboch triedach, zistíme, že sú úplne identické, takže sa ich pokúsime v triede TStvorec vyhodiť: kompilátoru to nevadí - pochopí, že sa majú zdediť,
ale projekt už nefunguje správne ...
"Virtuálne metódy"
Virtuálne metódy
  potrebovali by sme, aby TKruh.posun "pochopil", že bol zavolaný z potomka a teda nebude volať svoj TKruh.skry ale potomkovu metódu skry:
  TKruh.posun -- TKruh.skry     // skry je virtuálna
^                 \
 |                           \
TStvorec.posun --> TStvorec.skry  // skry je virtuálna
"zrejme sa to nedá urobiť..."
zrejme sa to nedá urobiť počas kompilácie, lebo TKruh.posun nemôže "tušiť", že niekedy v budúcnosti si niekto niekde inde naprogramuje veľa potomkov, ktoré budú volať TKruh.posun
"Polymorfizmus"
Polymorfizmus
metóda sa zdieľa v rôznych stupňoch objektovej hierarchie  ->
napr. vtedy, ak rôzne triedy zdedia "spoločnú" metódu (napr. metódu posun), ale detaily pre rôzne objekty zodpovedajú ich zvláštnostiam (napr. metóda skry)
"kompilátor - okamžité rozhodnutie pri..."
kompilátor - okamžité rozhodnutie pri statických metódach odložené rozhodnutie pri virtuálnych metódach
     zatiaľ  nevieš, ktorú metódu (ktorého objektu), keď príde čas volania, opýtaj sa inštancie (premennej typu objekt)
pri statických metódach kompilátor hľadá zodpovedajúce meno v hierarchii smerom k predkom od danej úrovne (kde je definovaná metóda)
"pri virtuálnych metódach nie kompilátor"
pri virtuálnych metódach nie kompilátor, ale počas behu sa hľadá zodpovedajúce meno v hierarchii smerom k predkom, ale od úrovne inštancie
včasná väzba = early binding - pri statických
neskorá väzba = late binding - pri virtuálnych
"Virtuálne metódy"
Virtuálne metódy
v deklarácii objektu virtual
ak je v nejakej triede virtuálna metóda => všetci potomkovia, ak majú metódu tohoto mena, mali by mať override (prekryje virtuálnu metódu) a s rovnakou hlavičkou - bez override sa táto definícia bude chápať ako "predefinovanie" virtuálnej na statickú
"každý objekt obsahuje VMT (..."
každý objekt obsahuje VMT (Virtual Method Table):
konštruktor objektu inicializuje napojenie na túto tabuľku
každá inštancia obsahuje len referenciu na túto (jedinú pre danú triedu) tabuľku - je to prvá položka v zázname
"hovoríme,"
hovoríme, že konštruktor môže byť použitý aj na inicializovanie stavových premenných - jeho "hlavná" funkcia je vyhradiť pamäť pre objekt a inicializovať VMT !!!
"Kompatibilita tried (objektových typov"
Kompatibilita tried (objektových typov)
kompatibilita je jednosmerná => odvodený typ dedí kompatibilitu so svojimi predkami (kompatibilita s predkami nie potomkami)
medzi inštanciami
medzi formálnymi a skutočnými parametrami
"máme deklarácie:"
máme deklarácie:
var a,c:TKruh;
    b:TStvorec;
potom je povolené:
     a:=TKruh.Create(...);
            b:=TStvorec.Create(...);
            c:=b;                // c referencuje tú istú inštanciu ako b
            c:=TStvorec.Create(...);
procedure zmen(k:TKruh);
begin
        k.ZmenFarbu(clBlue);
        k.posun(1,1);
end;
"a tiež môže byť volané"
a tiež môže byť volané:
zmen(b);
===> formálny parameter k je polymorfný objekt (rôznorodý)
===> potomok môže kdekoľvek nahradiť predka (predok môže zastupovať potomka)