AGB  ·  Datenschutz  ·  Impressum  







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

Typumwandlung mit Generika

Ein Thema von Panthrax · begonnen am 28. Mär 2009 · letzter Beitrag vom 29. Mär 2009
Antwort Antwort
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#1

Typumwandlung mit Generika

  Alt 28. Mär 2009, 18:35
Ich habe keine Möglichkeit es zu probieren, interessiere mich aber trotzdem für die Funktionstüchtigkeit folgender Methodenaufrufe:
Delphi-Quellcode:
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.
Kann mir jemand sagen, was da heraus kommt?
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.155 Beiträge
 
Delphi 12 Athens
 
#2

Re: Typumwandlung mit Generika

  Alt 29. Mär 2009, 08:52
virtual; bei TGenericClassB<T> weggemacht und am Ende noch ein ReadLn;,
dann kommt das raus:
Zitat:
B.Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
TClassB(B).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
TGenericClassB<TObject>(B).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
(B as TClassB).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
(B as TGenericClassB<TObject>).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
TClassA(B).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
TGenericClassA<TObject>(B).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
(B as TClassA).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
(B as TGenericClassA<TObject>).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
[add]
Prozedur in TGenericClassA<T> nicht virtual und dann überschrieben, kommt sowas raus:
Zitat:
B.Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
TClassB(B).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
TGenericClassB<TObject>(B).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
(B as TClassB).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
(B as TGenericClassB<TObject>).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
TClassA(B).Method1;
A: TGenericClassA<T>.Method1 aufgerufen.
TGenericClassA<TObject>(B).Method1;
A: TGenericClassA<T>.Method1 aufgerufen.
(B as TClassA).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
(B as TGenericClassA<TObject>).Method1;
B: TGenericClassB<T>.Method1 aufgerufen.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#3

Re: Typumwandlung mit Generika

  Alt 29. Mär 2009, 21:07
Danke!

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.
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
I.A

Registriert seit: 14. Jan 2007
83 Beiträge
 
#4

Re: Typumwandlung mit Generika

  Alt 29. Mär 2009, 21:25
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.
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#5

Re: Typumwandlung mit Generika

  Alt 29. Mär 2009, 21:31
Generics gibt es unter Win32 erst ab D2009
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.155 Beiträge
 
Delphi 12 Athens
 
#6

Re: Typumwandlung mit Generika

  Alt 29. Mär 2009, 21:54
da Links steht meißtens das, was man hauptsächlich verwendet ... und man muß ja nicht nur ein Delphi in den Pfötchen halten

Zitat von Panthrax:
Ich hatte gedacht, der Compiler verweigert die Typumwandlung "B as TClassA" mit "Inkompatible Typen".

So reagiert er jedenfalls auf "StringList as TComponent".
B und A sind ja verwandt ... is/as prüft ob die angegebene Klasse sich selber oder ein Vorfahre von sich ist.

TStringList > TStrings > TPersistent > TObject

also nur dieses hier geht
Delphi-Quellcode:
TStringList is TStringList
TStringList is TStrings
TStringList is TPersistent
TStringList is TObject
"TStringList is TComponent" geht nicht, da es kein Vorfahre ist und demnach TStringList keine Eigenschaften von TComponent besitzt.


[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;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#7

Re: Typumwandlung mit Generika

  Alt 29. Mär 2009, 22:58
Zitat von Panthrax:
TClassA ist schließlich kein Vorfahr von TClassB.
Doch, du legst schließlich nur Type Synonyms an. Da passiert in etwas soviel wie bei
type TFoo = TObject nämlich überhaupt nichts. Bei
TClassB is TClassA sieht der Compiler also nur
TGenericClassB<TObject> is TGenericClassA<TObject> Im Kompilat sind TClassA und TClassB völlig verschwunden.
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#8

Re: Typumwandlung mit Generika

  Alt 29. Mär 2009, 23:28
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:
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.
Ich hatte mir die Vorfahrlinien irgendwie so gedacht:
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.
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  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 17:41 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