o dziedziczeniu?

0

ma takie klesy.
chcialbym sie dowiedziec jak zadzialaja rozne sposoby przedefiniowywania metod.

TNADKlasa = class
{1}  procedure aaa;
{2}  procedure foo;
{3}  procedure bar; virtual;
{4}  procedure xxx; virtual;
end;

TPodKlasa = class(TKlasa)
{5}  procedure aaa;
{6}  procedure foo;
{7}  procedure bar;
{8}  procedure xxx; override;
end;

procedure TNADKlasa.aaa;
begin
  writeln('NADKlasa.aaa');
end;

procedure TNADKlasa.foo;
begin
  writeln('NADKlasa.foo');
end;

procedure TNADKlasa.bar;
begin
  writeln('NADKlasa.bar');
end;

procedure TNADKlasa.xxx;
begin
  writeln('KNADlasa.xxx');
end;

//////////////////////////////////////////////////////////

procedure TPodKlasa.aaa;  <-- w nadrzednej jest taka sama metoda
begin
  writeln('POD Klasa.aaa');
end;

procedure TPodKlasa.foo; <---  w nadrzednej klasie jest taka metoda ale nie virtualna! 
begin
  inherited;                      <--- czy to zadziala?
  writeln('POD Klasa.foo');
end;

procedure TPodKlasa.bar;  <-- w nadrzednej jest metoda virtualna ale przykryta bez override
begin
  writeln('POD Klasa.bar');
end;

procedure TPodKlasa.xxx;  <--- normalne przesterowanie(? -nie wiem jak to po polsku) 
begin
  inherited;
  writeln('POD Klasa.xxx');
end;





var A,B: TKlasa;
    X,Y: TPodKlasa;
begin
  A := TPodKlasa.create;  <--- tu jest dostep przez wskaznik na nadklase
  A.aaa;
  A.foo;
  A.bar;
  A.xxx;

  X := TPodKlasa.create;  <-- tu jest normalnie
  X.aaa;
  X.foo;
  X.bar;
  X.xxx;
  
  Y := A;  <-- a tu nie wiem jak:P
  Y.aaa;
  Y.foo;
  Y.bar;
  Y.xxx;

end;

No i teraz jest pytanie:
Co uzyskamy na wyjsciu....?

//heh krocej niz tego posta pewnie zajeloby mi napisanie programu i sprawdzenie samemu... :p

generalnie chodzi o to ze chcialbym miec klase ktora bylaby podstawa do budowy klas dziedziczacych.
w dziedziczacych klasach nadpisywalbym tylko niektore metody, a te ktorych nie potrzebuje zostalyby w
klasie nadrzednej. Jakich 'magicznych slow' (virtual, override, inherited, reintroduce...) musze uzyc zeby dzialalo to
bez wzgledu na rzutowanie czy jakies dziwne podejscie do konkretnych obiektow...

0
Johny_Morfina napisał(a)

generalnie chodzi o to ze chcialbym miec klase ktora bylaby podstawa do budowy klas dziedziczacych.
w dziedziczacych klasach nadpisywalbym tylko niektore metody, a te ktorych nie potrzebuje zostalyby w
klasie nadrzednej. Jakich 'magicznych slow' (virtual, override, inherited, reintroduce...) musze uzyc zeby dzialalo to
bez wzgledu na rzutowanie czy jakies dziwne podejscie do konkretnych obiektow...

Jesli chcesz robic klase bazowa z podstawowymi procedurami ktore potem nadpisujesz to nie ustawiaj magicznych słów.

type TBase=class
  public
  procedure Test(A,B,C:integer);
end;

type TKlasa1=class(TBase)
public
  procedure Test;
end;

procedure TBase.Test(A,B,C:integer);
begin
  ShowMessage(format('%d %d %d',[A,B,C]));
end;

procedure TKlasa1.Test;
begin
  inherited Test(1,2,3); //wykonaj procedure z klasy po ktorej dziedziczy TKlasa1 - Test(1,2,3)
  ShowMessage('Hello from TKlasa1');
end;

Dyrektywa virtual; w metodzie klasy bazujacej generalnie duzo nie zmienia w tym przykladzie, ale mozesz nadpisac cala procedure. Ma to chyba wplyw na metody w klasach dziedziczacych z TKlasa1... Nigdy sie w to nie zaglebialem bo nie bylo mi to potrzebne.

Ogolnie to popatrz w kompedium :)

0

jak masz tak

unit Unit1;

interface

type
  a1 = class
  protected
    procedure b;
  public
    procedure c;
  end;
  
  b1 = class(a1)
  protected
    procedure b;
  end;

  a2 = class
  protected
    procedure b; virtual;
  public 
    procedure c;
  end;

  b2 = class(a2)
  protected
    procedure b; override;
  end;

implementation

procedure a1.b;
begin
  writeln('a1');
end;

procedure a1.c;
begin
  b;
end;


procedure b1.b;
begin
  writeln('b1');
end;

procedure a2.b;
begin
  writeln('a2');
end;

procedure b2.b;
begin
  inherited;
  writeln('b2');
end;

procedure a2.c;
begin
  b;
end;

end.


//gdzies dalej
var
  bb1: b1;
  bb2: b2;
begin
  bb1 := b1.Create;
  bb2 := b2.Create;
  bb1.c;
  Writeln;
  bb2.c;
  Readln;
end.

to tam, gdzie nie masz virtual i override mimo iż zmienna jest typu pochodnego to metodab będzie wywołana z klasy bazowej, a dokładnie z pierwszej pochodnej klasy, która ma metodę c. I właśnie tutaj najlepiej widać po co to i dlaczego.

0

magiczne slowo virtual jest potrzebne przy nie-bezposrednim dostepie do obiektow

TNadKlasa = class
  procedure a; 
  procedure b; virtual;
end;

TPodKlasa = class(TNadKlasa)
  procedure a;
  procedure b; override;
end;


var NK: TNadKlasa;

begin
  NK := TPodKlasa.create;
  NK.a;     <--------Tu sie wykona procedura z NADKlasy
  NK.b;     <------- Tu sie wykona procedura z PODKlasy
end;

dzieki temu ze metoda jest virtual'na wywolywana jest metoda obiektu ktory rzeczywiscie znajduje sie pod wskaznikiem a nie ta odpowiadajaca typowi wskaznika. zapewne zmniejsza to troche wydajnosc programu ale daje bardzo duze mozliwosci.

1 użytkowników online, w tym zalogowanych: 0, gości: 1