AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Halb-virtuelle Methoden

Offene Frage von "Sir Rufo"
Ein Thema von Der schöne Günther · begonnen am 30. Dez 2014 · letzter Beitrag vom 30. Dez 2014
Antwort Antwort
Seite 1 von 2  1 2      
Der schöne Günther

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

Halb-virtuelle Methoden

  Alt 30. Dez 2014, 13:40
Delphi-Version: XE7
Ich bin zu ungeschickt, in den Weiten des Internets richtig danach zu suchen. Folgender Code:
Delphi-Quellcode:
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.
erzeugt die Ausgabe
Code:
interface variable
TMyBase
TMyChild

class type variable
TMyBase
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.

Warum ist das so? Könnte folgendes etwas damit zu tun haben?
http://docwiki.embarcadero.com/RADSt...mplementations


Lange Rede kurzer Sinn: Sollte ich bei implementierten Interface-Methoden nun eine virtual-Direktive dahintersetzen? Eigentlich kann ich mir das ja dann sparen...
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#2

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 13:47
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:
...
classVariable.interfaceProc();
...
sollte in einer AV resultieren, da die Instanz aufgrund der fehlenden Referenz nach dem Create wieder den ReferenceCount 0 erhält.

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;

Geändert von alda (30. Dez 2014 um 14:02 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 17:54
Das sollte schon bekannt sein, dass bei
Delphi-Quellcode:
var
  LInstance : TMyBase;
begin
  LInstance := TMyChild.Create;
  LInstance.interfaceProc; // ruft TMyBase.interfaceProc auf!!!
end;
eben die Methode TMyBase.interfaceProc aufgerufen wird, aufgrund der Deklaration von LInstance : TMyBase .

Aus diesem Grund muss die Methode zwingend als virtual deklariert werden, dann wird die auch in der abgeleiteten und erzeugten Klasse gefunden.

Allerdings funktioniert dies hier
Delphi-Quellcode:
var
  LInstance : TMyChild;
begin
  LInstance := TMyChild.Create;
  LInstance.interfaceProc; // ruft TMyChild.interfaceProc auf!!!
end;
wie erwartet
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#4

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 18:19
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

Geändert von Dejan Vu (30. Dez 2014 um 20:39 Uhr)
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 18:38
Hoppla, stimmt:
Ändere
Delphi-Quellcode:
   TMyChild = class(TMyBase, IMyInterface)
      procedure interfaceProc();// override;
   end;
zu
Delphi-Quellcode:
   TMyChild = class(TMyBase)
      procedure interfaceProc();// override;
   end;
und erhalte plötzlich
Code:
interface variable
TMyBase

class type variable
TMyBase
Total komisch.


Trotzdem macht der Compiler die Methoden irgendiwe "halb-virtuell", denn wenn ich classVariable zu TMyChild caste, ruft interfaceProc() mittels inherited völlig gelassen die Methode der Oberklasse auf. Obwohl nie jemand gesagt hat, dass diese Methode virtuell sein soll.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 18:46
Na dann versuch doch mal das hier:
Delphi-Quellcode:
var
  LBase : TMyBase;
  LChild : TMyChild;
begin
  LBase := nil;
  LChild := nil;

  LBase.interfaceProc;
  LChild.interfaceProc;
end;
Aha, jetzt wissen wir das auch
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 19:04


Mein Punkt ist: Niemand schreibt irgendwo virtual . Trotzdem wird sie "halb virtuell" gemacht: Halb, da ich von der Unterklasse mittels inherited die Methode der Oberklasse aufrufen kann obwohl niemand irgendwo override sagt.
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#8

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 19:21


Mein Punkt ist: Niemand schreibt irgendwo virtual . Trotzdem wird sie "halb virtuell" gemacht: Halb, da ich von der Unterklasse mittels inherited die Methode der Oberklasse aufrufen kann obwohl niemand irgendwo override sagt.
Die Eigenschaft "virtual" sagt ja auch nur aus, dass man die Methode überschreiben darf. Das "inherited" ruft einfach die geerbte Methode auf, das hat ja erstmal nichts mit der Eigenschaft virtual zu tun.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 20:21
Du kannst quasi jede Methode (private sind schwierig bis gar nicht zu erreichen) in einer Ableitung überschreiben, aber wenn die Methode nicht als virtual deklariert ist, dann bekommst du genau das Verhalten wie du es hier siehst/zeigst, ansonsten ist es so wie erwartet.

Ist eine Methode virtual , dann kann man sich mit Delphi-Referenz durchsuchenTVirtualMethodInterceptor in die Methodenaufrufe einklinken, bei allen anderen Methoden ist das nicht möglich. Das liegt an der Verwaltung der Klassenstruktur, die man mit genau diesem virtual festlegt.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 20:25
Die Dokumentation ist da auch eindeutig

http://docwiki.embarcadero.com/RADSt...ethodenbindung
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:14 Uhr.
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