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.211 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

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
 
#2

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
 
#3

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
 
#4

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
Dejan Vu
(Gast)

n/a Beiträge
 
#5

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 20:35
Ich muss mich korrigieren, das ist nicht 'typisch halbausgegorener Delphi-Mist', wie ich schrieb, sondern vollkommen korrekt, das das so ist. Verwirrend, aber korrekt.

TMyClass implementiert das Interface und die Methode interfaceproc und TMyChild schert sich einen feuchten Kericht darum und ersetzt/überschreibt (wortwörtlich) die Methode durch eine eigene Implementierung.

Dreckig, sollte verboten sein, aber legal.

PS: C# hätte in 'TMyChild' gerne das 'new' Schlüsselwort, damit man sieht, das 'interfaceproc' *neu* implementiert wurde, aber notwendig ist auch dort nicht...

Geändert von Dejan Vu (30. Dez 2014 um 20:40 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
 
#6

AW: Halb-virtuelle Methoden

  Alt 30. Dez 2014, 22:23
Ich habe das Beispiel mal erweitert, damit man die ganzen Spielarten sieht
Delphi-Quellcode:
program dp_183307;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

type
  IMyInterface = interface
    procedure interfaceProc1( );
    procedure interfaceProc2( );
  end;

  TMyBase = class( TInterfacedObject, IMyInterface )
    procedure interfaceProc1( ); // virtual;
    procedure interfaceProc2( ); virtual;
  end;

  TMyChild = class( TMyBase, IMyInterface )
    procedure interfaceProc1( ); // override;
    procedure interfaceProc2( ); override;
  end;

procedure TMyBase.interfaceProc1( );
begin
  WriteLn( 'TMyBase.interfaceProc1' );
end;

procedure TMyBase.interfaceProc2;
begin
  WriteLn( 'TMyBase.interfaceProc2' );
end;

procedure TMyChild.interfaceProc1( );
begin
  inherited;
  WriteLn( 'TMyChild.interfaceProc1' );
end;

procedure TMyChild.interfaceProc2;
begin
  inherited;
  WriteLn( 'TMyChild.interfaceProc2' );
end;

procedure Test1;
var
  LIntf: IMyInterface;
  LInst: TMyBase;
begin
  WriteLn( 'LInst[TMyBase] := TMyBase.Create' );
  LInst := TMyBase.Create;
  LInst.interfaceProc1;
  LInst.interfaceProc2;
  WriteLn( 'LIntf <- LInst' );
  LIntf := LInst;
  LIntf.interfaceProc1;
  LIntf.interfaceProc2;
end;

procedure Test2;
var
  LIntf: IMyInterface;
  LInst: TMyBase;
begin
  WriteLn( 'LInst[TMyBase] := TMyChild.Create' );
  LInst := TMyChild.Create;
  LInst.interfaceProc1;
  LInst.interfaceProc2;
  WriteLn( 'LIntf <- LInst' );
  LIntf := LInst;
  LIntf.interfaceProc1;
  LIntf.interfaceProc2;
end;

procedure Test3;
var
  LIntf: IMyInterface;
  LInst: TMyChild;
begin
  WriteLn( 'LInst[TMyChild] := TMyChild.Create' );
  LInst := TMyChild.Create;
  LInst.interfaceProc1;
  LInst.interfaceProc2;
  WriteLn( 'LIntf <- LInst' );
  LIntf := LInst;
  LIntf.interfaceProc1;
  LIntf.interfaceProc2;
end;

begin
  try
    WriteLn('Test1');
    Test1;
    WriteLn;
    WriteLn('Test2');
    Test2;
    WriteLn;
    WriteLn('Test3');
    Test3;
  except
    on E: Exception do
      WriteLn( E.ClassName, ': ', E.Message );
  end;
  ReadLn;

end.
Damit erhalten wir folgende Ausgabe
Code:
Test1
LInst[TMyBase] := TMyBase.Create
TMyBase.interfaceProc1
TMyBase.interfaceProc2
LIntf <- LInst
TMyBase.interfaceProc1
TMyBase.interfaceProc2

Test2
LInst[TMyBase] := TMyChild.Create
TMyBase.interfaceProc1
TMyBase.interfaceProc2
TMyChild.interfaceProc2
LIntf <- LInst
TMyBase.interfaceProc1
TMyBase.interfaceProc2
TMyChild.interfaceProc2

Test3
LInst[TMyChild] := TMyChild.Create
TMyBase.interfaceProc1
TMyChild.interfaceProc1
TMyBase.interfaceProc2
TMyChild.interfaceProc2
LIntf <- LInst
TMyBase.interfaceProc1
TMyChild.interfaceProc1
TMyBase.interfaceProc2
TMyChild.interfaceProc2
Jetzt kommt das Schmankerl ... und nehmen bei TMyChild das Interface weg TMyChild = class( TMyBase{, IMyInterface} ) .

Jetzt erhalten wir diese Ausgabe
Code:
Test1
LInst[TMyBase] := TMyBase.Create
TMyBase.interfaceProc1
TMyBase.interfaceProc2
LIntf <- LInst
TMyBase.interfaceProc1
TMyBase.interfaceProc2

Test2
LInst[TMyBase] := TMyChild.Create
TMyBase.interfaceProc1
TMyBase.interfaceProc2
TMyChild.interfaceProc2
LIntf <- LInst
TMyBase.interfaceProc1
TMyBase.interfaceProc2
TMyChild.interfaceProc2

Test3
LInst[TMyChild] := TMyChild.Create
TMyBase.interfaceProc1
TMyChild.interfaceProc1
TMyBase.interfaceProc2
TMyChild.interfaceProc2
LIntf <- LInst
TMyBase.interfaceProc1
TMyBase.interfaceProc2
TMyChild.interfaceProc2
Lustig, gell?
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 09:02 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