Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Vererbung mit mehrfach eingeschränktem TypParamater (https://www.delphipraxis.net/180380-vererbung-mit-mehrfach-eingeschraenktem-typparamater.html)

Alexander I 16. Mai 2014 10:43

Vererbung mit mehrfach eingeschränktem TypParamater
 
Hallo,

ich möchte eine Klasse mit zweifach eingeschränktem TypParameter nach der Art TFoo<T: Interface1,Interface2> vererben.

Die Klasse0, ist die Klasse mit den zwei einschränkenden TypParametern.

An Klasse1 soll nun Klasse0 mit dem InterfaceTypParameter IKlasse1 vererbt werden.

Bekomme aber die Fehlermeldung
[dcc32 Fehler] : E2514 Typparameter 'T' muss Interface 'IKlasse2' unterstützen

Was ist falsch?


interface

type
IKlasse1 = interface;

IKlasse2 = interface;

Klasse0< T : IKlasse1, IKlasse2 > = class;

Klasse1 = class;

Klasse2 = class;



IKlasse1 = interface end;

IKlasse2 = interface end;

Klasse0< T : IKlasse1, IKlasse2 > = class(TInterfacedObject)

function Transform : T;

end;


Klasse1 = class( Klasse0< IKlasse1 > ) end; ===>> hier erfolgt die Fehlermeldung: Typparameter 'T' muss Interface 'IKlasse2' unterstützen

Klasse2 = class( Klasse0< IKlasse2 > ) end; ===>> hier erfolgt die Fehlermeldung: Typparameter 'T' muss Interface 'IKlasse1' unterstützen



implementation

end.




Gruß

Alexander

Neutral General 16. Mai 2014 11:07

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Naja die Typeinschränkungen müssen halt beide erfüllt werden.

Delphi-Quellcode:
Klasse0< T : IKlasse1, IKlasse2 > = class;
=>

T muss IKlasse1 UND IKlasse2 unterstützen. Nicht ODER.

Du solltest deinen Code übrigens mit Delphi-Tags versehen. Das machts etwas übersichtlicher!

himitsu 16. Mai 2014 11:46

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Und ohne die Forward-Deklarationen sieht der Code auch gleich viel übersichtlicher aus. :angel:
Delphi-Quellcode:
interface

type
  IKlasse1 = interface end;
  IKlasse2 = interface end;

  Klasse0<T: IKlasse1, IKlasse2> = class(TInterfacedObject)
    function Transform: T;
  end;

  Klasse1 = class(Klasse0<IKlasse1>) end;
  Klasse2 = class(Klasse0<IKlasse2>) end;

implementation

end.
Ich hätte zwar auch ODER gedacht, aber wenn das stimmt, dann kannst du das vielleicht über eine Interfacevererbung lösen:
Delphi-Quellcode:
type
  IBasisKlasse = interface end;
  IKlasse1 = interface(IBasisKlasse) end;
  IKlasse2 = interface(IBasisKlasse) end;

  Klasse0<T: IBasisKlasse> = class(TInterfacedObject) // oder Klasse0<T: IBasisKlasse> = class(TInterfacedObject, IBasisKlasse)
    function Transform: T;
  end;

  Klasse1 = class(Klasse0<IKlasse1>) end;
  Klasse2 = class(Klasse0<IKlasse2>) end;
Oder du schränkst es nicht all zu sehr ein:
Delphi-Quellcode:
type
  IKlasse1 = interface end;
  IKlasse2 = interface end;

  Klasse0<T: interface> = class(TInterfacedObject)
    function Transform: T;
  end;

  Klasse1 = class(Klasse0<IKlasse1>) end;
  Klasse2 = class(Klasse0<IKlasse2>) end;
[edit]
Ich mein natürlich IKlasse0, statt IBasisKlasse :angle:

Alexander I 16. Mai 2014 16:29

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Danke für die schnellen Antworten.

Ich hatte gedacht, gehofft das man sagen kann das für T entweder die eine oder andere IKlasse gilt.


Probiert hatte ich auch

IKlasse1 = interface(IUnknown) end;

IKlasse2 = interface(IUnknown) end;

Klasse0<T : IKlasse1, IKlasse2> = class(TInterfacedObject)

function Transform : T;

end;


Klasse1 = class( Klasse0< IKlasse1 , IKlasse2> ) end;


mit FehlerMeldung [dcc32 Fehler] E2003 Undeklarierter Bezeichner: 'Klasse0<,>'

jetzt hätte ich gedacht das beide IKlassen angenommen werden.

Gruß
Alexander

Stevie 16. Mai 2014 17:28

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Einschränkungen für Typparameter können kein "oder". Alles was du hinter dem ":" angibst, muss restlos erfüllt sein.

himitsu 16. Mai 2014 18:55

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Aso, deswegen heißt es also
Delphi-Quellcode:
E2553 Klassentypeinschränkung darf nicht mehr als einmal angegeben werden

Stevie 16. Mai 2014 19:14

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Zitat:

Zitat von himitsu (Beitrag 1259097)
Aso, deswegen heißt es also
Delphi-Quellcode:
E2553 Klassentypeinschränkung darf nicht mehr als einmal angegeben werden

Bei Klassen geht natürlich nur eine, wir haben ja in Delphi keine Mehrfachvererbung. Bei Interfaces gehen natürlich mehrere, aber die müssen dann ebend alle implementiert sein.

Das ist manchmal ein bisschen niggelich, wenn man z.B. eine Generische Klasse oder Methode bauen will, die für Klassen und Interfaces geht, aber nicht für andere Datentypen. Dann muss man die unterschiedlich nennen.

Alexander I 19. Mai 2014 10:39

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Hallo,

was muß ich an der Zeile ändern, damit der Compiler keinen Fehler anzeigt.

Hab schon etliches ausprobiert aber leider keinen Treffer gelandet.


Klasse1 = class( Klasse0< IKlasse1 , IKlasse2> ) end;


==> FehlerMeldung [dcc32 Fehler] E2003 Undeklarierter Bezeichner: 'Klasse0<,>'


Gruß

Alexander

Sir Rufo 19. Mai 2014 11:28

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Du hast
  1. immer noch nicht die Delphi-Tags verwendet :roll:
  2. bei
    Delphi-Quellcode:
    Klasse0<T:IKlasse1,IKlasse2>
    angegeben, dass du genau einen Typ-Parameter angeben möchtest und versuchst dort jetzt zwei anzugeben

So geht es (aber ich weiß nicht, ob es das ist, was du willst)
Delphi-Quellcode:
program dp_180380;

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

uses
  System.SysUtils;

type
  IKlasse1 = interface
    ['{E90AABBF-1711-4E09-AD38-63A6F53C2DBA}']
  end;

  IKlasse2 = interface
    ['{8D8349B5-F5C2-4F85-9DAC-606D7307667A}']
  end;

  TKlasse0<T : IKlasse1, IKlasse2> = class( TInterfacedObject )

  end;

  TKlasse = class( TInterfacedObject, IKlasse1, IKlasse2 )

  end;

  TKlasse1 = class( TKlasse0<TKlasse> )
  end;

begin
  try
    { TODO -oUser -cConsole Main : Code hier einfügen }
  except
    on E : Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;

end.

Alexander I 20. Mai 2014 09:43

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Danke für die Tips.

Mich stört das ich eine Klasse haben muß, in der beide Interfaces auch noch implementiert werden müßen.
Delphi-Quellcode:
TKlasse = class( TInterfacedObject, IKlasse1, IKlasse2 )
.
Das wollte ich aber vermeiden.

Ich möchte in TKlasse1 nicht auf IKlasse2 zugreifen können. Was man machen könnte wäre
Delphi-Quellcode:
  TKlasse1 = class( TKlasse0<TKlasse> , IKlasse1 ) end;
.
Dann hätte ich aber doppelten Code, auch wenn ich in TKlasse virtual und abstract auf die Methoden von IKlasse1 lege.


Nichts desto trotz, mein Ziel wäre gewesen in
Delphi-Quellcode:
Klasse0<T : IKlasse1, IKlasse2> = class(TInterfacedObject)
function Transform(element : T) : T;
end;
auf die Methoden und Eigenschaften von element zugriefen zu können (element.Eigenschaft1) . Aber das geht leider nicht.

Oder doch?

Gruß und Danke

Alexander

Der schöne Günther 20. Mai 2014 10:10

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Ich komme nicht ganz hinterher, was letztendlich dein Ziel ist.

Du hast zwei vollkommen verschiedene Interfaces. Eine Klasse soll jetzt entweder mit IMeinInterface1 ODER IMeinInterface2 parametrisiert werden können. Typeinschränkungen sind immer UND.

Entweder es macht Sinn und du bildest ein gemeinsames Über-Interface (welches fortan die einzige Parametrisierungs-Einschränkung ist)
Delphi-Quellcode:
type
   IMyBaseInterface = interface
      // ?
   end;

   IMyInterface1 = interface(IMyBaseInterface)
      // ?
   end;

   IMyInterface2 = interface(IMyBaseInterface)
      // ?
   end;

   TMeineGenerischeKlasse<T: IMyBaseInterface> = class

   end;
Oder es ist sicher dass es immer bei diesen beiden Interfaces bleiben wird. Dann würde ich die Klasse überhaupt nicht generisch machen sondern halt zwei verschiedene Methoden anbieten- Einmal für
Delphi-Quellcode:
IMyInterface1
und einmal für
Delphi-Quellcode:
IMyInterface2
.


Vielleicht liegt es an mir, aber ich persönlich habe immer große Schwierigkeiten mit vollkommen abstrakten Bezeichnern wie
Delphi-Quellcode:
TKlasse1 = class( TKlasse0<TKlasse> , IKlasse1 ) end;
. Kannst du vlt. ein ganz konkretes Beispiel geben? Kann ja frei erfunden sein, aber irgendwas zum "Anfassen"...

Dejan Vu 20. Mai 2014 11:57

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Zitat:

Zitat von Alexander I (Beitrag 1259479)
Mich stört das ich eine Klasse haben muß, in der beide Interfaces auch noch implementiert werden müßen.

Das geht doch gar nicht anders. Woher willst Du denn wissen, ob Du auf Property-A vom IKlasse1 zugreifen kannst, wenn deine Klasse dieses Interface gar nicht implementiert...

Mir scheint, deine OOP-Überlegungen bedürfen einer gründlicher Überarbeitung.
Zitat:

Zitat von Der schöne Günther (Beitrag 1259486)
Ich komme nicht ganz hinterher, was letztendlich dein Ziel ist.

Zitat:

Zitat von Sir Rufo (Beitrag 1259316)
...aber ich weiß nicht, ob es das ist, was du willst...

Dem schließe ich mich an.

Alexander I 20. Mai 2014 12:24

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab mal ein pdf erstellt, in dem "ersichtlich" ist wie ich mir das gedacht habe.

Es gibt zwei verschiedene Klassen: Punkte und Vektoren.

Dies erben von einer "abstrakten" BaseTransformationsKlasse die nix kann außer eine Instanz der TranslateKlasse in ihrer eigenen Methode BaseTransformations.Translate zu

instanziieren.

Die TranslateKlasse soll aber von Anfang an wissen welchem Typ sie erwarten soll, damit ich auf die Propertys zugreifen kann, nämlich element.X.

In C# gibts sowas mit where T : .... und da kann man auf Methoden und Propertys sofort zugreifen.


Gruß
Alexander

Uwe Raabe 20. Mai 2014 13:04

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Warum nimmst du nicht einfach IBase als gemeinsamen Vorfahrtyp anstatt der beiden abgeleiteten Interfaces?

Delphi-Quellcode:
BaseTransformation<T: IBase>

Translate<T: IBase>

Der schöne Günther 20. Mai 2014 14:18

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Noch ohne auf die PDF geschaut zu haben: Das
Delphi-Quellcode:
where
in C# ist bei den Typeinschränkungen doch auch nichts anderes als der Doppelpunkt in Delphi. Und statt
Delphi-Quellcode:
new()
heißt es
Delphi-Quellcode:
constructor
.

Code:
public void meineMethode<T>(T meinParameter) where T: ISomeBaseInterface, ISomeOtherInterface
bedeutet in C# doch genauso, dass T beide Interfaces implementieren muss.

PS: Punkte und Vekoren. Ich wusste es :-D

PPS: Warum überhaupt der Unterschied zwischen Punkten und Vektoren? Transformation wie bspw. Translation wird ja sowieso eigentlich doch über einen Vektor in homogenisierter Form mit einer Transformationsmatrix erledigt. Darüber lassen sich alle möglichen Operationen abwickeln.
Aber das führt jetzt nur vom eigentlichen Thema weg... (oder?)

PPPS: Warum möchtest du an der Stelle wissen, ob es nun ein IPoint oder IVector ist? Die richtige Typeinschränkung an diesen Fall wäre übrigens, anders als auf der PDF, IBase und nicht IPoint UND IVector.
Wenn du jetzt zur Laufzeit unbedingt wissen willst ob es nun ein IPoint oder IVector ist kannst du das mit
Delphi-Quellcode:
Supports(..)
überprüfen.


Delphi-Quellcode:
program Project3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
   IBaseInterface = interface
      //
   end;

   IChildInterface1 = interface(IBaseInterface)
   ['{65F8AA65-0EED-4D26-A396-26999CD9E316}']
      //
   end;

   IChildInterface2 = interface(IBaseInterface)
   ['{8F390B34-CCF6-4908-B205-D4CD9CF5D3BE}']
      //
   end;

   TIChildClass1 = class(TInterfacedObject, IBaseInterface, IChildInterface1)
      // Es müssen IBaseInterface UND IChildInterface1 angegeben werden.
      // Ja, IBaseInterface ist eigentlich obsolet, aber so ist Delphi halt
      // Stört mich ehrlich gesagt auch
   end;

   TIChildClass2 = class(TInterfacedObject, IBaseInterface, IChildInterface2)
      //
   end;

   TSomeRecord = record
      public class procedure someMethod<T: IBaseInterface>(const someInput: T); static;

   end;

{ TSomeRecord }

class procedure TSomeRecord.someMethod<T>(const someInput: T);
begin
   if Supports(someInput, IChildInterface1) then
      WriteLn('Es ist ein IChildInterface1')
   else if Supports(someInput, IChildInterface2) then
      WriteLn('Es ist ein IChildInterface2')
   ;

end;

begin
  try
   TSomeRecord.someMethod( TIChildClass2.Create() );
  except
    on E: Exception do
     Writeln(E.ClassName, ': ', E.Message);
  end;

  ReadLn;
end.

PPPPS: Generics und im Nachhinein wieder aufdröseln um im Detail nochmal zu schauen was drinsteckt führt Generics ad absurdum. So meine Meinung ohne gründlich drüber nachgedacht zu haben.

Uwe Raabe 20. Mai 2014 15:19

AW: Vererbung mit mehrfach eingeschränktem TypParamater
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1259526)
PPPPS: Generics und im Nachhinein wieder aufdröseln um im Detail nochmal zu schauen was drinsteckt führt Generics ad absurdum. So meine Meinung ohne gründlich drüber nachgedacht zu haben.

Sehe ich ähnlich. Gleiches gilt wohl sehr häufig auch für Klassen- und Interface-Vererbung. Wenn ich wissen muss, was für ein Abkömmling das ist, mache ich wahrscheinlich was falsch.


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