Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Generics Struktur-/Typen-Problem (https://www.delphipraxis.net/196302-generics-struktur-typen-problem.html)

hzzm 9. Mai 2018 13:05

Delphi-Version: 5

Generics Struktur-/Typen-Problem
 
Guten Tag,

ich habe hier ein strukturelles Problem:
Delphi-Quellcode:
type
  TRundesObjekt = class
    Radius: Integer;
    Beschreibung: String;
    procedure Kollidieren; virtual; abstract;
  End;

  TBall = class(TRundesObjekt)
    AnzahlDerNaehte: Integer;
    procedure Kollidieren; override;
  End;

  TKartoffel = class(TRundesObjekt)
    MitSchale: Boolean;
    procedure Kollidieren; override;
  End;

  TSack<T: TRundesObjekt> = class
    Material: String;
    Inhalt: TArray<T>;
    procedure Leeren;
  End;
 
  TSackFuellerModel<T: TRundesObjekt> = class
    MSack: TSack<T>;
  End;

  TSackFuellerAdapter<T: TRundesObjekt> = class
  private
    Model: TSackFuellerModel<T>;
  End;

implementation

procedure TSack<T>.Leeren;
begin
  SetLength(Inhalt, 0);
end;

procedure TBall.Kollidieren;
begin
  DoSoftMagic();
end;

procedure TKartoffel.Kollidieren;
begin
  DoHardMagic();
end;
Das Problem kriege ich aber beim Erstellen, wo ich ja die Generische Kette runter alles in Abhaengigkeit von entweder TBall oder TKartoffel generiere:
Delphi-Quellcode:
SackFuellerAdapter := TSackFuellerAdapter<TBall>.Create;
-> Inkompatible Typen: SackFueller.TSackFuellerAdapter<TRundesObjekt> und SackFueller.TSackFuellAdapter<TBall>

Wenn ich mit
Delphi-Quellcode:
SackFuellerAdapter := TSackFuellerAdapter<TRundesObjekt>.Create;
erstelle, ist es doch gar nicht spezifiziert auf TBall oder TKartoffel?
Irgendwie denke ich da gerade falsch. Es muss sich doch alles aufgrund des angegebenen Typen einstellen, daher sollte ich ihn beim obersten Create doch explizit angeben, oder wie/wo soll sich sonst ergeben, welche jeweiligen Versionen (TBall- oder TKartoffel-Prozeduren etc.) dann verwendet werden?

Danke fuers Lesen.

TiGü 9. Mai 2018 13:19

AW: Generics Struktur-/Typen-Problem
 
Delphi-Quellcode:
SackFuellerAdapter: TSackFuellerAdapter<TRundesObjekt>;
ändern zu
SackFuellerAdapter: TSackFuellerAdapter<TBall>;
ändern zu
SackFuellerBallAdapter: TSackFuellerAdapter<TBall>;
mit Sahne oben drauf:
Delphi-Quellcode:
type
  TSackFuellerBallAdapter = TSackFuellerAdapter<TBall>;

var
  SackFuellerAdapter: TSackFuellerBallAdapter;

...
begin
  SackFuellerAdapter := TSackFuellerBallAdapter.Create;
end;

hzzm 9. Mai 2018 13:35

AW: Generics Struktur-/Typen-Problem
 
Hm, Danke.
Gibt es irgendeine Moeglichkeit, das gleiche Objekt bedarfsweise mit beidem zu beschalten?

Bei Deiner Loesung muss ich ja bei der Variablen-Deklaration von SackFuellerAdapter schon mit angeben, um was es sich handelt.
Ich hatte gehofft, ich koennte das bis zum Create() offen lassen, so dass man auf allgemeingueltige Elemente auch Zugriff hat, ohne an jeder Stelle eine Weiche zu basteln:
Delphi-Quellcode:
if Gegebenheit1 then
  SackFuellerBallAdapter.Abfuellen
else if Gegebenheit2 then
  SackFuellerKartoffelAdapter.Abfuellen;
Das wollte ich mir eigentlich durchgaengig ersparen
->
Delphi-Quellcode:
SackFuellerAdapter.Abfuellen;

hzzm 9. Mai 2018 13:49

AW: Generics Struktur-/Typen-Problem
 
Mit anderen Worten: Ich suche die Delphi-Syntax, die aussagt:
Variable kann genau von Typ X oder von Typ Y sein.

Diese Funktionalitaet hatte ich mir urspruenglich von meinem Split-Konzept "TBall oder TKartoffel", oder von Generics insgesamt erhofft.
Ich scheitere nur gerade daran, das durchzupruegeln... es laeuft immer darauf raus, am Ende doch Typen-Weichen bauen zu muessen, oder?

Stevie 9. Mai 2018 13:57

AW: Generics Struktur-/Typen-Problem
 
Stichwort: Varianz

https://de.wikipedia.org/wiki/Kovari..._Kontravarianz
http://delphisorcery.blogspot.de/201...-variance.html

freimatz 11. Mai 2018 11:21

AW: Generics Struktur-/Typen-Problem
 
Irgend wo musst Du doch festlegen welchen Typ Du haben willst.

Wir haben solche Konstruktionen oft. Typischerweise wird irgendwo wird ein Aufzählungstyp ermittelt. In einer Factory wird dann anhand diesem dann die Klasse bestimmt und erzeugt. Oft gibt es auch noch eine Registry wo sich die konkreten Implementation auf den Aufzählungstyp regisitrieren.
Dazwischen gibt es oft einen Klassenreferenz. In Deinem Falle wäre es:
Delphi-Quellcode:
type TRundesObjektClass class of TRundesObjekt;


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:12 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