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
Der schöne Günther

Registriert seit: 6. Mär 2013
6.199 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.199 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
Antwort Antwort


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 03:55 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