![]() |
Generische Array-Propertys
Ich kämpfe gerade mit dem Verständnis von Generics. Die Deklaration des generischen offenen Arrays klappt klaglos:
Code:
Das läuft, so weit so gut. Wenn ich das jetzt aber anwenden will, klappt nix mehr.
type
TValue<T> = class protected a: array of T; function GetT(const Index: Integer): T; procedure SetT(const Index: Integer; const Value: T); end; TAStr = TValue<String>; TAInt = TValue<Integer>; .. implementation function TValue<T>.GetT(const Index: Integer): T; begin Result := a[Index]; end; procedure TValue<T>.SetT(const Index: Integer; const Value: T); begin a[Index] := Value; end; Simples Beispiel:
Code:
Wo liegt mein Denkfehler? Wie komme ich denn nun an die Items ran?
TTest = class
private aStr: TAStr; aInt: TAInt; published property s0: String index 0 read GetT<String> write SetT<String> ; property i0: Integer index 0 read GetT<Integer> write SetT<Integer> ; end; |
AW: Generische Array-Propertys
Definiere "klappt nix mehr". Die Properties sind vom Typ einer Klasse, werden sie auch instanziert? Und wieso sind die Getter und Setter der umgebenden Klasse TTest generisch?
|
AW: Generische Array-Propertys
Klappt nix mehr heißt nur, dass ich nicht herausbekomme, wie ich auf die jeweiligen Items nun zugreifen kann.
Wenn die Getter und Setter nicht generisch sind, brauche ich doch gar keine Generics. Dann kann ich auch einfach Klassen für jeden Array-Typ schreiben, die ihre Get/Set einzeln bekommen. Das kann ich aber schon seit TurboPascal. |
AW: Generische Array-Propertys
Erstmal: keine SetLength?
Und read/write greift auf Methoden in der Klasse zu, welche es in deinem TTest garnicht gibt. (was dir garantiert der Compiler auch sagt) Von den Methoden in den Sub-Klassen weiß niemand etwas. |
AW: Generische Array-Propertys
Delphi-Quellcode:
program Project2;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Math; type TValue<T> = class protected a: TArray<T>; function GetT(const Index: Integer): T; procedure SetT(const Index: Integer; const Value: T); end; TAStr = class(TValue<string>) public property s0: string index 0 read GetT write SetT; end; TAInt = class(TValue<Integer>) public property i0: Integer index 0 read GetT write SetT; end; TTest = class private aStr: TAStr; aInt: TAInt; public constructor Create(); destructor Destroy; override; public property MyStrings: TAStr read aStr; property MyIntegers: TAInt read aInt; end; function TValue<T>.GetT(const Index: Integer): T; begin if InRange(Index, System.Low(a), System.High(a)) then begin Result := a[Index]; end else begin Result := System.Default(T); end; end; procedure TValue<T>.SetT(const Index: Integer; const Value: T); begin if Index >= Length(a) then begin SetLength(a, Index + 1); end; a[Index] := Value; end; constructor TTest.Create; begin inherited; aStr := TAStr.Create; aInt := TAInt.Create; end; destructor TTest.Destroy; begin aStr.Free; aInt.Free; inherited; end; procedure TestStrings; var MyStringValue: TAStr; begin MyStringValue := TAStr.Create; MyStringValue.s0 := 'Hello World'; Writeln(MyStringValue.s0); MyStringValue.Free; end; procedure TestIntegers; var MyIntegerValue: TAInt; begin MyIntegerValue := TAInt.Create; MyIntegerValue.i0 := 0815; Writeln(MyIntegerValue.i0); MyIntegerValue.Free; end; procedure TestTest; var MyTest: TTest; begin MyTest := TTest.Create; MyTest.aStr.s0 := 'Huhu'; MyTest.aInt.i0 := 123; Writeln(MyTest.aStr.s0); Writeln(MyTest.aInt.i0); MyTest.Free; end; begin ReportMemoryLeaksOnShutdown := True; try TestStrings; TestIntegers; TestTest; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; Readln; end. |
AW: Generische Array-Propertys
Erst mal vielen Dank für Eure Antworten!
Natürlich gibt es auch ein SetLength usw., der Code dazu ist für meine Frage aber nicht relevant. Deshalb habe ich hier lediglich den Ausschnitt kopiert, der für meine Frage relevant ist: Wie greift man in Klassen, die Gebrauch von diesen Generischen Klassen macht, auf die einzelnen Items zu? Zu gut deutsch, was muss hier stehen, damit ich die Property-Zugriffe compilieren kann?
Code:
@TiGü:
TTest = class
private aStr: TAStr; aInt: TAInt; published property s0: String index 0 read GetT<String> write SetT<String> ; <=========== hier steckt der Fehler; im read/write property i0: Integer index 0 read GetT<Integer> write SetT<Integer> ; end; Das property MyStrings: TAStr read aStr; property MyIntegers: TAInt read aInt; weiß ich natürlich, kein Ding. Aber ich benötige wirklich die einzelnen Items in den Arrays als published propertys. Es baut sich hiernach eine Klassenhierarchie auf, die unterschiedlichste (sowohl Benamung als auch Anzahlen) Strings, Integer usw. benötigen, deren Namen mittels RTTI für nachgelagerte Operationen benötigt werden. Ohne Generics habe ich das Zeugs ja schon, aber ich schreibe diese Zugriffe und Prüfungen für jeden Typ separat derzeit. Das wollte ich gern generisch (für mich übersetzt: abstrakt?) machen, damit eine Änderung sofort für alle Typen funzt. |
Brett vorm Kopf
:lol:Heureka, man ich hatte ja so ein Brett vorm Kopf :lol:
Klar, es muss natürlich einmal noch ein simpler Setter/Getter pro benutztem Array geschrieben werden. Mann, wie kann man nur :oops: |
AW: Generische Array-Propertys
Ah, du hast die Antwort schon selber gefunden.
Aber falls der Nächste in achtdreiviertel Jahren beim Googlen hier lang kommt: Obigen Code aus meiner Antwort ergänzen mit:
Delphi-Quellcode:
type
TTest = class private aStr: TAStr; aInt: TAInt; public constructor Create; destructor Destroy; override; function GetInteger(const Index: Integer): Integer; function GetString(const Index: Integer): String; procedure SetInteger(const Index, Value: Integer); procedure SetString(const Index: Integer; const Value: String); published property s0: String index 0 read GetString write SetString; property i0: Integer index 0 read GetInteger write SetInteger ; end; ... constructor TTest.Create; begin inherited; aStr := TAStr.Create; aInt := TAInt.Create; end; destructor TTest.Destroy; begin aStr.Free; aInt.Free; inherited; end; function TTest.GetInteger(const Index: Integer): Integer; begin Result := Self.aInt.i0; end; function TTest.GetString(const Index: Integer): String; begin Result := Self.aStr.s0; end; procedure TTest.SetInteger(const Index, Value: Integer); begin Self.aInt.i0 := Value; end; procedure TTest.SetString(const Index: Integer; const Value: String); begin Self.aStr.s0 := Value; end;
Delphi-Quellcode:
procedure TestTest;
var MyTest: TTest; begin MyTest := TTest.Create; MyTest.s0 := 'Huhu'; MyTest.i0 := 123; Writeln(MyTest.s0); Writeln(MyTest.i0); MyTest.Free; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:46 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