Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi virtual und override (https://www.delphipraxis.net/53267-virtual-und-override.html)

Hador 13. Sep 2005 12:33


virtual und override
 
Das folgendes funktioniert ist mir klar:
Delphi-Quellcode:
unit Unit3;
interface

type xy = class
  x, y: integer;
  function get_str: string; virtual;
end;

type yz = class(xy)
  function get_str: string; override;
end;

implementation
function xy.get_str: string;
begin result := #32; end;
function yz.get_str: string;
begin result := #33; end;
end.
Aber wiso funktioniert auch folgendes? Bzw. worin liegt da der Unterschied?
Denn hier wird die Funktion get_str ja auch überschrieben, jedoch ohne dass sie vorher per virtual als überschreibbar deklariert wurde.

Delphi-Quellcode:
unit Unit2;
interface

type xy = class
  x, y: integer;
  function get_str: string;
end;

type yz = class(xy)
  function get_str: string;
end;

implementation
function xy.get_str: string;
begin result := #32; end;
function yz.get_str: string;
begin result := #33; end;
end.

Bernhard Geyer 13. Sep 2005 13:33

Re: virtual und override
 
Der unterschied ist dann gegeben wenn Du ein Objekt des Typs yz in einer Variable des Typs xy hast.

Im ersten Fall mit virtual/override wird die Methode von yz aufgerufen da in der Methodentabelle die Einsprungsadresse von der Implementierung in yz steht.

Im zweiten Fall wird die Methode von xy aufgerufen, da die Variable von diesem Typ ist und in der Methodentabelle die Implementierung auf xy steht.

jbg 13. Sep 2005 14:24

Re: virtual und override
 
Zitat:

Zitat von Bernhard Geyer
Im zweiten Fall [..] und in der Methodentabelle die Implementierung auf xy steht.

Im zweiten Fall gibt es gar keinen Eintrag in der VMT. Der Compiler ersetzt den Aufruf durch die direkte Adresse der Methode, die er im Gegensatz zu virtuellen Methoden kennt.

Hador 13. Sep 2005 16:21

Re: virtual und override
 
Erstmal danke für die Antworten. :thumb:
Da tun sich dann aber bei mir gleich mal folgende Fragen auf: :gruebel:

1. Warum eine Variable vom Typ xy Definieren, wenn Der Variable der Typ yz zugewiesen wird.
Also warum
Delphi-Quellcode:
var x: xy
begin
  x := yz.create;
end;
und nicht
Delphi-Quellcode:
var x: yz
begin
  x := yz.create;
end;
2. Warum kann ich der Variable vom Typ xy ein Objekt vom Typ yz zuweisen.
Andersherum währe es ja noch zu verstenen, denn yz beinhaltet ja xy aber xy ist doch nur ein Teil von yz.

EDIT: Evt. verstehe ich das ja, wenn ihr mir mal 'n praktisches Beispiel vorwerft. :wink:

tommie-lie 13. Sep 2005 16:35

Re: virtual und override
 
Zitat:

Zitat von Hador
1. Warum eine Variable vom Typ xy Definieren, wenn Der Variable der Typ yz zugewiesen wird.

Stell dir vor du sammelst daten in Objekten. Die Daten haben alle eine ähnliche Struktur, unterscheiden sich aber doch in rgendetwas. Also schreibst du eine Vaterklasse und leitest davon deine Klassen ab. Jetzt kriegst du einen Datenstrom mit 100 Datensätzen und willst die irgendwo unterbringen. Also kannst du ein Array der Vaterklasse erzeugen und kannst in dieses Array lauter Objekte der Kindklasse stecken, obwohl das Array eigentlich vom Typ der Vaterklasse ist. Zur Laufzeit schaust du dann, von welcher Art der aktuelle datensatz ist und erzeugst entsprechend das richtige Objekt. Würdest du für jede Art von Datensatz ein eigenes Array des richtigen Typs vorhalten, kann es unübersichtlich werden.

Zitat:

Zitat von Hador
2. Warum kann ich der Variable vom Typ xy ein Objekt vom Typ yz zuweisen.

Weil Klassen in einer Hierarchie nach oben zuweisungskompatibel sind. Du kannst also einer Variable einer Vaterklasse immer ein Objekt einer abgeleiteten Klasse übergeben, egal die wievieilte Ableitung es ist. Beispielsweise kann eine Variable vom Typ TControl alle Controls der VCL beinhalten, von Memo bis Button, weil alle VCL-Controls von TControl abgeleitet sind, obwohl bei einigen noch Klassen dazwischenliegen (z.B. TWinControl, TCustomMemo, etc).

Zitat:

Zitat von Hador
Andersherum währe es ja noch zu verstenen, denn yz beinhaltet ja xy aber xy ist doch nur ein Teil von yz.

Eben deswegen geht es.
Weil xy nur ein Teil von yz ist, kansnt du ein Objekt von yz einer Variable vom Typ xy zuweisen, weil der Compiler sicher sein kann, daß alles, was über die Variable zugänglich ist (an Feldern und Methoden) auch in dem Objekt von yz existieren. Andersrum hätte man die Klasse yz gegenüber xy erweitern können. Weise ich jetzt einer Variable vom Typ yz ein Objekt vom Typ xy zu, ist nicht der gesamte Speicher, den ich durch die Variable zugreifen kann, allokiert, weil ja die Klasse yz größer ist als xy.

Hador 13. Sep 2005 16:54

Re: virtual und override
 
Danke das habe ich gebraucht. :thumb:

Jetzt sehe ich klarer.

MaBuSE 13. Sep 2005 17:20

Re: virtual und override
 
Zitat:

Zitat von Hador
Danke das habe ich gebraucht. :thumb:
Jetzt sehe ich klarer.

Man sollte sich aber über die Auswirkungen vom Verdecken der Methoden bewust sein.
Da können sich leicht Fehler in ein Programm einschleichen, die man dann manchmal lange suchen muss ;-)

Zitat:

Zitat von Hador
EDIT: Evt. verstehe ich das ja, wenn ihr mir mal 'n praktisches Beispiel vorwerft.

Unterschiede zwischen Überschreiben und Verdecken
Wenn in einer Methodendeklaration dieselben Bezeichner- und Parameterangaben wie bei einer geerbten Methode ohne die Anweisung override angegeben werden, wird die geerbte Methode durch die neue Deklaration verdeckt. Beide Methoden sind jedoch in der abgeleiteten Klasse vorhanden, in der die Methode statisch gebunden wird.
Bei T2 werden Compilerwarnungen ausgegeben, das die Methoden verdeckt sind.
Mithilfe der Anweisung reintroduce kann verhindert werden, dass der Compiler Warnungen ausgibt, wenn eine zuvor deklarierte virtuelle Methode verdeckt wird, aber das Verhalten ist trotzdem das Selbe.

Unterschiede zwischen virtuellen und dynamischen Methoden
Virtuelle und dynamische Methoden sind von der Semantik her identisch. Sie unterscheiden sich nur bei der Implementierung der Aufrufverteilung zur Laufzeit. Virtuelle Methoden werden auf Geschwindigkeit, dynamische Methoden auf Code-Größe optimiert.
Im Allgemeinen kann mit virtuellen Methoden polymorphes Verhalten am effizientesten implementiert werden. Dynamische Methoden sind hilfreich, wenn in einer Basisklasse eine große Anzahl überschreibbarer Methoden deklariert ist, die von vielen abgeleiteten Klassen geerbt, aber nur selten überschrieben werden.

Delphi-Quellcode:
type
  T1 = class(TObject)
    procedure A; virtual;
    procedure B; dynamic;
    procedure C;
  end;
  T2 = class(T1)
    procedure A; // Methoden sind neu deklariert, aber nicht überschrieben
    procedure B;
    procedure C;
  end;
  T3 = class(T1)
    procedure A; override; // Methoden sind überschrieben
    procedure B; override;
//    procedure C; override; // Fehlermeldung, es können keine statischen Methoden überschrieben werden
  end;
...
var
  Obj1: T1;
  Obj2: T2;
  Obj3: T3;
begin
  // das ist klar
  Obj1 := T1.Create;
  Obj1.A; // T1.A wird aufgerufen
  Obj1.B; // T1.B wird aufgerufen
  Obj1.C; // T1.C wird aufgerufen
  Obj1.Free;

  // das ist klar
  Obj2 := T2.Create;
  Obj2.A; // T2.A wird aufgerufen
  Obj2.B; // T2.B wird aufgerufen
  Obj2.C; // T2.C wird aufgerufen
  Obj2.Free;

  // das ist klar
  Obj3 := T3.Create;
  Obj3.A; // T3.A wird aufgerufen
  Obj3.B; // T3.B wird aufgerufen
  Obj3.C; // T1.C wird aufgerufen, da nicht überschrieben
  Obj3.Free;

  // Achtung: Das ist oft nicht gewünscht
  Obj1 := T2.Create;
  Obj1.A; // T1.A wird aufgerufen
  Obj1.B; // T1.B wird aufgerufen
  Obj1.C; // T1.C wird aufgerufen
  T2(Obj1).A; // T2.A wird aufgerufen
  T2(Obj1).B; // T2.B wird aufgerufen
  T2(Obj1).C; // T2.C wird aufgerufen
  Obj1.Free;

  // Achtung: So sollte es (meistens) sein
  Obj1 := T3.Create;
  Obj1.A; // T3.A wird aufgerufen
  Obj1.B; // T3.B wird aufgerufen
  Obj1.C; // T1.C wird aufgerufen, da nicht überschrieben
  Obj1.Free;
end;

MaBuSE 13. Sep 2005 18:03

Re: virtual und override
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe obiges Beispiel mal in mein Delphi getippt und etwas erweitert :-)

Ich hoffe nun ist der Unterschied zwischen verdecken und überschreiben klar.

Viel Spaß.

Hador 13. Sep 2005 19:12

Re: virtual und override
 
Zitat:

Zitat von MaBuSE
Man sollte sich aber über die Auswirkungen vom Verdecken der Methoden bewust sein.
Da können sich leicht Fehler in ein Programm einschleichen, die man dann manchmal lange suchen muss ;-)

Da is mir grad noch aufgefallen:

Sobald man der neuen Prozedur/Funktion jedoch mehr Parameter zuweist, funktioniert override nicht mehr, bzw. Delphi lässt das nicht zu. Das verdecken funktioniert jedoch. Gibt es dort auch eine Möglichkeit die alte Methode zu überschreiben, oder macht Delphi da dann sozusagen eine Überladene Mthode raus, und sucht sich aufgrund der Parameteranzahl bzw. des Parametertyps die passende Methode raus ?

tommie-lie 13. Sep 2005 19:26

Re: virtual und override
 
Zitat:

Zitat von Hador
Sobald man der neuen Prozedur/Funktion jedoch mehr Parameter zuweist, funktioniert override nicht mehr, bzw. Delphi lässt das nicht zu. Das verdecken funktioniert jedoch. Gibt es dort auch eine Möglichkeit die alte Methode zu überschreiben, oder macht Delphi da dann sozusagen eine Überladene Mthode raus, und sucht sich aufgrund der Parameteranzahl bzw. des Parametertyps die passende Methode raus ?

Beim Überschreiben von Methoden muss die Funktionssignatur gleich bleiben, aber du kannst die MEthode im Parent zusätzlich zu virtual noch mit overload deklarieren und dann in der abgeleiteten Klasse ebenfalls. Dann brauchst du aber eigenltich kein override mehr, weil es eben eine andere Methode ist, d.h. du wirst auch nicht über eine Variable des Vatertyps auf die überladenen Methoden der Kindklasse zugreifen können.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:37 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz