![]() |
Typumwandlung mit Generika
Ich habe keine Möglichkeit es zu probieren, interessiere mich aber trotzdem für die Funktionstüchtigkeit folgender Methodenaufrufe:
Delphi-Quellcode:
Kann mir jemand sagen, was da heraus kommt?
program Typumwandlung;
{$AppType Console} uses SysUtils, Classes; type TGenericClassA<T> = class public procedure Method1; virtual; end; TGenericClassB<T> = class(TGenericClassA<T>) public procedure Method1; override; virtual; end; TClassA = TGenericClassA<TObject>; TClassB = TGenericClassB<TObject>; procedure TGenericClassA<T>.Method1; begin WriteLn('A: TGenericClassA<T>.Method1 aufgerufen.'); end; procedure TGenericClassB<T>.Method1; begin WriteLn('B: TGenericClassB<T>.Method1 aufgerufen.'); end; procedure Test; var B: TClassB; begin B:=TClassB.Create; try { B } WriteLn('B.Method1;'); B.Method1; WriteLn('TClassB(B).Method1;'); TClassB(B).Method1; WriteLn('TGenericClassB<TObject>(B).Method1;'); TGenericClassB<TObject>(B).Method1; WriteLn('(B as TClassB).Method1;'); (B as TClassB).Method1; WriteLn('(B as TGenericClassB<TObject>).Method1;'); (B as TGenericClassB<TObject>).Method1; { A } WriteLn('TClassA(B).Method1;'); TClassA(B).Method1; WriteLn('TGenericClassA<TObject>(B).Method1;'); TGenericClassA<TObject>(B).Method1; WriteLn('(B as TClassA).Method1;'); (B as TClassA).Method1; WriteLn('(B as TGenericClassA<TObject>).Method1;'); (B as TGenericClassA<TObject>).Method1; finally B.Free; end; end; begin Test; end. |
Re: Typumwandlung mit Generika
virtual; bei TGenericClassB<T> weggemacht und am Ende noch ein ReadLn;,
dann kommt das raus: Zitat:
Prozedur in TGenericClassA<T> nicht virtual und dann überschrieben, kommt sowas raus: Zitat:
|
Re: Typumwandlung mit Generika
Danke! :thumb:
Ich finde es schon ein bisschen seltsam, dass sich B: TClassB nach TClassA typumwandeln lässt. Ich hatte gedacht, der Compiler verweigert die Typumwandlung "B as TClassA" mit "Inkompatible Typen". So reagiert er jedenfalls auf "StringList as TComponent". TClassA ist schließlich kein Vorfahr von TClassB. Allerdings ist TClassA inhaltsgleich mit der Vorfahrklasse TClassB = TGenericClassB<TObject> << TGenericClassA<TObject>, da TClassA = TGenericClassA<TObject> definiert wurde. Die Laufzeitinformationen zu den Typen TClassA und bspw. einer dritten, konkreten, gleich definierten Klasse TClassC = class(TGenericClassA<TObject>) müssten sich doch zumindest im Klassennamen unterscheiden, und bilden damit unterschiedliche Klassen. Liege ich falsch? Ich weiß nicht, irgendwie scheint mir das gewöhnungsbedürftig. |
Re: Typumwandlung mit Generika
Funktioniert das nich erst ab Delphi 2009? Ihr habt als verwendete Delphi Version Delphi 7 Enterprise angegeben.
Oder geht das nur mit der .NET Verstion? Ich jedenfalls habe neben D7 Personal auch Turbo Delphi Explorer. Dort habe ich das Testprojekt hinkopiert. In eine Konsolenanwendung rein. Unit Classes ergänzt. Test; zwischen BEGIN END. des Hauptprogrammes geschrieben. Fehlermeldung: [Pascal Fehler] Project1.dpr(9): E2029 '=' erwartet, aber '<' gefunden Dort steht bei mir: type TGenericClassA<T> = class //das hier public procedure Method1; virtual; Scheint so das Generics erst später in Delphi eingeführt wurden. Soviel ich weiß, ab Delphi 2009. |
Re: Typumwandlung mit Generika
Generics gibt es unter Win32 erst ab D2009
|
Re: Typumwandlung mit Generika
da Links steht meißtens das, was man hauptsächlich verwendet ... und man muß ja nicht nur ein Delphi in den Pfötchen halten :angel:
Zitat:
TStringList > TStrings > TPersistent > TObject also nur dieses hier geht
Delphi-Quellcode:
"TStringList is TComponent" geht nicht, da es kein Vorfahre ist und demnach TStringList keine Eigenschaften von TComponent besitzt.
TStringList is TStringList
TStringList is TStrings TStringList is TPersistent TStringList is TObject [add] andersrum geht nur dieses nicht (ungültige Typumwandlung)
Delphi-Quellcode:
procedure Test;
var A: TClassA; begin A := TClassA.Create; try ... WriteLn('(A as TClassB).Method1;'); (A as TClassB).Method1; WriteLn('(A as TGenericClassB<TObject>).Method1;'); (A as TGenericClassB<TObject>).Method1; finally A.Free; end; ReadLn; end; |
Re: Typumwandlung mit Generika
Zitat:
Delphi-Quellcode:
nämlich überhaupt nichts. Bei
type TFoo = TObject
Delphi-Quellcode:
sieht der Compiler also nur
TClassB is TClassA
Delphi-Quellcode:
Im Kompilat sind TClassA und TClassB völlig verschwunden.
TGenericClassB<TObject> is TGenericClassA<TObject>
|
Re: Typumwandlung mit Generika
Sebastian hat es eigentlich schon gesagt. Trotz rotem Kasten:
Das StringList-Beispiel ist aus der Welt ohne Generika. Dort kann man eine Variable nicht in einen Typ umwandeln, der außerhalb der Vorfahrlinie steht ("StringList as TComponent"). In der Welt mit Generika scheint (schien!) aber genau das zu funktionieren. Nachdem es sich bei mir etwas gesetzt hat, ist bei mir, glaube ich, der Groschen gefallen. Der folgende Quelltext soll nur noch einmal meine Überlegung verdeutlichen (Win32 ohne Generika, siehe TClassA1 und TClassA2):
Delphi-Quellcode:
Ich hatte mir die Vorfahrlinien irgendwie so gedacht:
program Project1;
{$AppType Console} uses SysUtils; type TGenericClassA = class public procedure Method1; virtual; end; TGenericClassB = class(TGenericClassA) public procedure Method1; override; end; { TClassA = TGenericClassA<TObject>; ist etwa } TClassA1 = TGenericClassA; { und nicht } TClassA2 = class(TGenericClassA); TClassB = TGenericClassB; { TGenericClassA } procedure TGenericClassA.Method1; begin WriteLn('A: TGenericClassA.Method1 aufgerufen'); end; { TGenericClassB } procedure TGenericClassB.Method1; begin WriteLn('B: TGenericClassB.Method1 aufgerufen'); end; procedure Test; var B: TClassB; begin B:=TClassB.Create; try { 1 } TClassA1(B).Method1; (B as TClassA1).Method1; { 2 } TClassA2(B).Method1; (B as TClassA2).Method1; { [Pascal Fehler] Project1.dpr(50): E2010 Inkompatible Typen: 'TClassA2' und 'TGenericClassB' } finally B.Free; end; end; begin Test; ReadLn; end. TGenericClassA<T> >> TGenericClassB<T> TGenericClassA<TObject> >> TGenericClassB<TObject> >> TClassB TGenericClassA<TObject> >> TClassA TClassA wäre also nicht in der Linie von TClassB. Tatsächlich sind die Linien so: TGenericClassA<T> >> TGenericClassB<T> TGenericClassA<TObject> >> TGenericClassB<TObject> = TClassB {2} TGenericClassA<TObject> = TClassA {2} Aus 1 und 2 ließe sich also formulieren: TClassA >> TGenericClassB<TObject> = TClassB Damit liegt TClassA in der Vorfahrlinie und die Typumwandlung "B as TClassA" ist keine Überraschung mehr. -- Vielen Dank! Ich glaub' ich muss mir unbedingt ne Möglichkeit verschaffen mit Generika selbst ein bisschen herumzuspielen... @I.A: Ja, allerdings, ich habe keine Möglichkeit, Generika einmal testweise auszuprobieren. Deshalb habe ich jemanden gefragt. Himitsu war so freundlich. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:54 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 by Thomas Breitkreuz