![]() |
Delphi-Version: XE7
Halb-virtuelle Methoden
Ich bin zu ungeschickt, in den Weiten des Internets richtig danach zu suchen. Folgender Code:
Delphi-Quellcode:
erzeugt die Ausgabe
program Project15; {$APPTYPE CONSOLE} {$R *.res}
uses System.SysUtils; type IMyInterface = interface procedure interfaceProc(); end; TMyBase = class(TInterfacedObject, IMyInterface) procedure interfaceProc();// virtual; end; TMyChild = class(TMyBase, IMyInterface) procedure interfaceProc();// override; end; procedure TMyBase.interfaceProc(); begin WriteLn('TMyBase'); end; procedure TMyChild.interfaceProc(); begin inherited; Writeln('TMyChild'); end; var interfaceVariable: IMyInterface; classVariable: TMyBase; begin WriteLn('interface variable'); interfaceVariable := TMyChild.Create(); interfaceVariable.interfaceProc(); Write(sLineBreak); WriteLn('class type variable'); classVariable := TMyChild.Create(); classVariable.interfaceProc(); readln; end.
Code:
Sprich: Spreche ich die Instanz mit einer Interface-Variable an wird die Methode behandelt, als hätte ich virtual angegeben. Nehme ich die Klassenreferenz wird sie nicht virtual behandelt.
interface variable
TMyBase TMyChild class type variable TMyBase Warum ist das so? Könnte folgendes etwas damit zu tun haben? ![]() Lange Rede kurzer Sinn: Sollte ich bei implementierten Interface-Methoden nun eine virtual-Direktive dahintersetzen? Eigentlich kann ich mir das ja dann sparen... |
AW: Halb-virtuelle Methoden
Ist doch völlig logisch, der Aufruf über die variable "classVariable" hat rein garnichts mit dem Interface zu tun und sollte so auch nicht benutzt werden - also ja, hier bräuchtest Du ein virtual - oder übersehe ich hier etwas ?
Übrigens: der Aufruf von
Delphi-Quellcode:
sollte in einer AV resultieren, da die Instanz aufgrund der fehlenden Referenz nach dem Create wieder den ReferenceCount 0 erhält.
...
classVariable.interfaceProc(); ... Edit: Jetzt sehe ich worauf Du hinaus willst, hatte die Ausgabe von "TMyBase" UND "TMyChild" beim ansprechen der "interfaceVariable" übersehen. Dieses Verhalten ist mir in der tat noch nicht aufgefallen, aber ich habe auch sehr selten solch eine Konstellation. Spontan würde ich die Klassen in der Tat so deklarieren, wie Du es angedeutet hast:
Delphi-Quellcode:
TMyBase = class(TInterfacedObject, IMyInterface)
procedure interfaceProc(); virtual; end; TMyChild = class(TMyBase) procedure interfaceProc(); override; end; |
AW: Halb-virtuelle Methoden
Das sollte schon bekannt sein, dass bei
Delphi-Quellcode:
eben die Methode
var
LInstance : TMyBase; begin LInstance := TMyChild.Create; LInstance.interfaceProc; // ruft TMyBase.interfaceProc auf!!! end;
Delphi-Quellcode:
aufgerufen wird, aufgrund der Deklaration von
TMyBase.interfaceProc
Delphi-Quellcode:
.
LInstance : TMyBase
Aus diesem Grund muss die Methode zwingend als
Delphi-Quellcode:
deklariert werden, dann wird die auch in der abgeleiteten und erzeugten Klasse gefunden.
virtual
Allerdings funktioniert dies hier
Delphi-Quellcode:
wie erwartet :)
var
LInstance : TMyChild; begin LInstance := TMyChild.Create; LInstance.interfaceProc; // ruft TMyChild.interfaceProc auf!!! end; |
AW: Halb-virtuelle Methoden
Also in meinen Augen ist das mal wieder 'typisch halbausgegorener Delphi-Mist'.
Die 2. Deklaration (TMyChild implementiert IMyInterface) ist redundant, da es von TMyClass abgeleitet ist und diese ja schon das Interface implementiert. Weiterhin müsste die 'interfaceproc' Routine als virtual deklariert werden, da sie ja überschrieben wird. Es muss doch egal sein, ob ich über das Interface oder die Klasse eine Implementierung aufrufe. So, wie das hier von Delphi umgesetzt wurde, ist das doch totaler Murks: Wir erlauben z.B. nur die Verwendung von Interfacevariablen, die Instantiierung erfolgt nur über eine Fabrik. Intern jedoch kann es durchaus sein, das eine Klasse direkt verwendet wird, um z.B. auf public Methoden zugreifen zu können, die nicht im Interface angegeben sind. Grauslich. Edit: Der obige Text ist -bis auf den Einwand mit der redundanten Angabe des Interfaces in der Deklaration von TMyChild- Quatsch. Ich lass ihn aber so. Begründung siehe folgende Beiträge |
AW: Halb-virtuelle Methoden
Hoppla, stimmt:
Ändere
Delphi-Quellcode:
zu
TMyChild = class(TMyBase, IMyInterface)
procedure interfaceProc();// override; end;
Delphi-Quellcode:
und erhalte plötzlich
TMyChild = class(TMyBase)
procedure interfaceProc();// override; end;
Code:
Total komisch. :roteyes:
interface variable
TMyBase class type variable TMyBase Trotzdem macht der Compiler die Methoden irgendiwe "halb-virtuell", denn wenn ich
Delphi-Quellcode:
zu TMyChild caste, ruft
classVariable
Delphi-Quellcode:
mittels
interfaceProc()
Delphi-Quellcode:
völlig gelassen die Methode der Oberklasse auf. Obwohl nie jemand gesagt hat, dass diese Methode virtuell sein soll.
inherited
|
AW: Halb-virtuelle Methoden
Na dann versuch doch mal das hier:
Delphi-Quellcode:
Aha, jetzt wissen wir das auch ;)
var
LBase : TMyBase; LChild : TMyChild; begin LBase := nil; LChild := nil; LBase.interfaceProc; LChild.interfaceProc; end; |
AW: Halb-virtuelle Methoden
:wiejetzt:
Mein Punkt ist: Niemand schreibt irgendwo
Delphi-Quellcode:
. Trotzdem wird sie "halb virtuell" gemacht: Halb, da ich von der Unterklasse mittels
virtual
Delphi-Quellcode:
die Methode der Oberklasse aufrufen kann obwohl niemand irgendwo
inherited
Delphi-Quellcode:
sagt.
override
|
AW: Halb-virtuelle Methoden
Zitat:
|
AW: Halb-virtuelle Methoden
Du kannst quasi jede Methode (private sind schwierig bis gar nicht zu erreichen) in einer Ableitung überschreiben, aber wenn die Methode nicht als
Delphi-Quellcode:
deklariert ist, dann bekommst du genau das Verhalten wie du es hier siehst/zeigst, ansonsten ist es so wie erwartet.
virtual
Ist eine Methode
Delphi-Quellcode:
, dann kann man sich mit
virtual
![]()
Delphi-Quellcode:
festlegt.
virtual
|
AW: Halb-virtuelle Methoden
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:56 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz