![]() |
Von TObjectList<T> erben?
Ich würde gerne meine angepasste Objektliste auf Generics umstellen.
Nur ich frag mich schon die ganze Zeit wie nun die Klassendefinition aussehen muss.
Delphi-Quellcode:
Es müsste doch eigentlich die letzte Variante sein oder?
TNonFoodList = class(TObjectList<TNonFood>)
TNonFoodList<T: TNonFood> = class(TObjectList<TNonFood>) //Gesehen bei StackOverflow TNonFoodList<TNonFood> = class(TObjectList<T: class>) Da TObjectList<T> so definiert ist:
Delphi-Quellcode:
:gruebel: :gruebel:
TObjectList<T: class> = class(TList<T>)
|
Re: Von TObjectList<T> erben?
Hi,
für das was Du vermutlich anstellen willst, ist die Variante 1 die Richtige. Ich gehe davon aus, dass Du eine verwaltete Liste mit Objekten vom Typ TNonFood erstellen möchtest. Grüße Michael |
Re: Von TObjectList<T> erben?
Ja richtig erkannt es soll vom Typ TNonFood sein.
Is mir irgendwie entfallen das zu erwähnen :roll: Danke für die Hilfe ich werds nachher mal probieren. Edit:
Delphi-Quellcode:
Ergibt:
TNonFoodList = class(TObjectList<TNonFood>)
Zitat:
|
Re: Von TObjectList<T> erben?
Generics.Collections hast du aber schon geöffnet?
PS: Bei Listen ist Vererbung unüblich, eine Komposition ist oft einfacher. |
Re: Von TObjectList<T> erben?
Zitat:
Jetzt compilliert es schon mal :D Getestet hab ich aber noch nicht. Was meinst du mit Komposition? Im Moment bin ich bei der Umstellung auf Generics eh am überlegen ob eventuell ein TDictionary<TValue, TKey> nicht besser ist. :roll: Eigentlich herrscht über die Generics bei mir grosse Verwirrung :? |
Re: Von TObjectList<T> erben?
[quote="ryLIX"]
Zitat:
und die generischen Klassen genauso benannt hat, wie die Normalen. Somit kommt es zu solchen blöden Namenspoblemen und irreführenden Fehlermeldungen. |
Re: Von TObjectList<T> erben?
Zitat:
Es ist z.B. auch nicht möglich, eine Variable eines generischen Typs zu deklarieren (außer als Feld in einer generische Klasse):
Delphi-Quellcode:
läßt sich nicht compilieren.
var
List: TObjectList<T>; Damit scheidet eine Komposition schon mal aus. Man muss sich Generics einfach als Klassen-Vorlagen vorstellen. Erst durch die Bestimmung des oder der variablen Typen wird daraus eine verwendbare herkömmliche Klasse. Mit
Delphi-Quellcode:
wird implizit eine Klassendeklaration erstellt, bei der alle "T" in TObjectList<T> durch TNonFood ersetzt werden.
type
TNonFoodList = class(TObjectList<TNonFoodList>); |
Re: Von TObjectList<T> erben?
Zitat:
Sowas läßt sich z.B. bei mir compilieren:
Delphi-Quellcode:
var
List: TObjectList<TEdit>; Zitat:
(es sei denn es wurde vorher schonmal eine gleichartige Typ-Kombination für diesem Generic kompiliert, dann wird diese natürlich wiederverwendet) Dieses würde alle nötigen Codes doppelt in die Anwendung reinkompiliert ... einmal alles mit TEdit und dann nochmal alles mit TButton: Es wäre praktisch so, als wenn man zwei Objektlisten im QuellCode "parallel" erstellt hätte.
Delphi-Quellcode:
var
ListA: TObjectList<TEdit>; ListB: TObjectList<TButton>; |
Re: Von TObjectList<T> erben?
Zitat:
Zitat:
|
Re: Von TObjectList<T> erben?
Achso ja, wenn du eine Variable deklarierst, dann müssen natürlich auch alle Typen aufgelöst werden,
denn "T" kennt der Compiler "zufällig" nicht und an dieser Stelle möchte er ja gern die Klasse erstellen, wofür er nunmal der fertig/vollständig deklarierten Typ benötigt ... z.B. für die spätere Speicherverwaltung und Dergleichen. Witzig wäre es für dich geworden, wenn rein zufällig irgendein Typ mit dem Namen "T" an dieser Stelle existiert hätte. :lol: |
Re: Von TObjectList<T> erben?
Zitat:
|
Re: Von TObjectList<T> erben?
Zitat:
Delphi-Quellcode:
Bei Typen funktioniert es gleichermaßen:
procedure Überladen; overload; // "Überladen()"
procedure Überladen(const Wert: Integer); overload; // "Überladen(Integer)"
Delphi-Quellcode:
Gerade das macht es so einfach, und man muss sich nicht so viele Bezeichner merken.
TObjectList = class { ... } end; // "TObjectList()"
TObjectList<T> = class { ... } end; // "TObjectList(Typ)" |
Re: Von TObjectList<T> erben?
Zitat:
/add: Und Panthrax muss ich auch recht geben, ist imo eher eine Vereinfachung als potentielle Verwirrung. Zitat:
Delphi-Quellcode:
Solange wir aber nicht über TList<TDictionary<... reden, ist das aber ebenfalls unüblich, man sollte im Code einfach direkt TObjectList<TNonFood> verwenden.
type TNonFoodList = TObjectList<TNonFood>;
Zitat:
Zitat:
|
Re: Von TObjectList<T> erben?
Also unter FPC werden Generics so spezialisiert:
Delphi-Quellcode:
Es wundert mich wirklich, dass das unter Delphi vollkommen anders aussieht.
type
TNonFoodList = specialize TList<TNonFood>; |
Re: Von TObjectList<T> erben?
Zitat:
in C ist es auch nicht nötig: ![]() |
Re: Von TObjectList<T> erben?
Zitat:
|
Re: Von TObjectList<T> erben?
Hab grad mal auf FreePascal.org nachgeschlagen - die Syntax hat sich mal wieder geändert.
Jetzt geht's angeblich auch so: (noch nicht getestet)
Delphi-Quellcode:
Und so 'nen PublicJoke-Proposal mit generischen Units gibt's auch noch. :shock:
// tom proposal:
type TNonFoodList = TObjectList<TNonFood>; // dannym proposal type TNonFoodList = TObjectList of TNonFood; // plugwash: type TNonFoodList = TObjectList[TNonFood]; Da steigt doch kein Mensch mehr durch... [ADD] Die ham sogar generische Routinen eingeführt - sowas hab ich noch nie gesehen |
Re: Von TObjectList<T> erben?
Zitat:
![]() |
Re: Von TObjectList<T> erben?
Zitat:
Zitat:
Delphi-Quellcode:
class procedure Generics.Collections.TArray.Sort<T>(...);
|
Re: Von TObjectList<T> erben?
Ne, so:
Delphi-Quellcode:
Ziemlich am Ende der Wiki-Seite steht aber was davon, es würde bisher nur eine Notlösung für Generics laufen. Also wer weiß, ob das wirklich schon alles klappt...
function generic(T) Max(A, B: T): T;
begin if A < B then Result := B else Result := A; end; [ADD] Grad getestet, läuft noch nicht. Sind alles nur Zukunftspläne, die da auf der Wikiseite stehen. |
Re: Von TObjectList<T> erben?
Zitat:
(oder kam das auch später?) Zitat:
Delphi-Quellcode:
function generic(T: TTreeItem) MyFunc(A: T): T;
begin // do something with the tree item end; // oder function generic(T) Max(A, B: T): T; begin if A < B then Result := B else Result := A; end; |
Re: Von TObjectList<T> erben?
Zitat:
Ok, das "Hm!?" war missverständlich, was ich sagen wollte "Was ist mit dem hier!?" -- Ist gleichwertig:
Delphi-Quellcode:
Derzeit ist noch Achtung geboten mit generischen Methoden:
class procedure TKlasse.DelphiProzedur<T>(const Value: T);
procedure FPCProzedur(T)(const Wert: T); // Aufruf: TKlasse.DelphiProzedur<Integer>(123); FPCProzedur(Integer)(123); ![]() |
Re: Von TObjectList<T> erben?
Ich muss noch ma was Fragen...
Die generische Liste bietet mir ja bei der ObjectList die möglichkeit auf TypeCasts zu verzichten. Also sollte doch bei meiner TNonFoodList welche von TObecjtList<TNonFood> erbt folgender aufruf funktionieren:
Delphi-Quellcode:
TNonFood enthält natürlich ein Feld welches Artikelname heißt.
var
s: string; begin s:= locNonFoodList.Items[X].Artikelname; end; Nur wird mir Artikelname im Code Editor rot unterstrichen aber er compilliert trotzdem... Warum? :gruebel: Und dann wollte ich mein CustomSort übernehmen und hab da gleich das nächste Problem ...
Delphi-Quellcode:
Markiert wird end));
procedure TNonFoodList.Sortieren(SortBy: TNonFoodArtikelEnum);
begin NonFoodArtikelSortieren := SortBy; Self.Sort(TComparer<TNonFood>.Construct( function (Left, Right: TNonFood): Integer begin case NonFoodArtikelSortieren of Artikelname: CompareText(Left.Artikelname, Right.Artikelname); Menge: CompareValue(Left.Menge, Right.Menge); Preis: CompareValue(Left.Preis, Right.Preis); Kosten: CompareValue(Left.Kosten, Right.Kosten); end; end)); end; Compilermeldung: Zitat:
|
Re: Von TObjectList<T> erben?
Zitat:
Irgendein Vollpfosten beim damaligen Borland war der Meinung, dass man statt den Parser des Compilers einen neuen in C# geschriebenen Parser für ErrorInsight braucht. Und der ist nicht mal 90% Delphi-konform. Für ein ErrorInsight braucht man aber 100%, sonst kann man das ganze Feature wegschmeißen. Leider haben sie es von 2004 bis jetzt noch nicht hinbekommen, den ErrorInsight-Parser alle Sprachfeatures beizubringen. Generic-Klassen und vor allem Generic-Arrays werden von wenig bis gar nicht richtig erkannt. Überladene Methode in einer if-Abfrage (=> if FileAge(..) then) unterringelt er, da der Parser sich immer für die erste Deklaration entscheidet (die bei FileAge natürlich deprecated ist). Usw. Am besten schaltet man das Feature ab, wenn man mit Generics was macht. |
Re: Von TObjectList<T> erben?
Zitat:
Zitat:
Zitat:
Zitat:
![]() |
Re: Von TObjectList<T> erben?
Zitat:
|
Re: Von TObjectList<T> erben?
Zitat:
Ich hab es noch einmal nach diesem Beispiel hier versucht: ![]() Ändert aber nichts an der Fehlermeldung. Seltsam ist das TList<>.Sort als Pararmeter "AComparer Void-Typ" erwartet.
Delphi-Quellcode:
Und bei
procedure TList<T>.Sort(const AComparer: IComparer<T>);
Delphi-Quellcode:
Wäre der von mir verwendete Aufruf korrekt:
TComparer<T> = class(TInterfacedObject, IComparer<T>)
Delphi-Quellcode:
Kann es sein das es ein Bug im Compiler ist? :gruebel:
function Construct(const Comparison: TComparison<T>): IComparer<T>;
Tante Edit: Also ich hab mal das komplette Beispiel nach gebaut. Da funktioniert es ohne Fehler. Kann es sein das <T> in diesem Fall keine Klasse sein darf? :roteyes: |
Re: Von TObjectList<T> erben?
So jetzt hab ichs.
So geht des CustomSort:
Delphi-Quellcode:
Aber die Probleme gehen weiter... :(
type
TNonFoodComparer = class (TComparer<TNonFood>) function Compare(const Left, Right: TNonFood): Integer; override; end; ... { TNonFoodComparer } function TNonFoodComparer.Compare(const Left, Right: TNonFood): Integer; begin case NonFoodArtikelSortieren of Artikelname: Result := CompareText(Left.Artikelname, Right.Artikelname); Menge: Result := CompareValue(Left.Menge, Right.Menge); Preis: Result := CompareValue(Left.Preis, Right.Preis); Kosten: Result := CompareValue(Left.Kosten, Right.Kosten); end end; ... { TNonFoodList } procedure TNonFoodList.Sortieren(SortBy: TNonFoodArtikelEnum); begin NonFoodArtikelSortieren := SortBy; Self.Sort(TNonFoodComparer.Default); end; Ich habe versucht den Bug den himitsu ![]()
Delphi-Quellcode:
Hier hab ich nun Undeklarierter Bezeichner: 'T'
constructor TNonFoodList.Create(const AComparer: IComparer<T>;
AOwnsObjects: Boolean); begin inherited Create(AComparer, AOwnsObjects); end; :? so langsam nervts mich.... |
Re: Von TObjectList<T> erben?
Was versuchtst Du denn zu beheben, wenn Du nur den geerbten Kontruktor aufrufst? Außerdem: Die Fehlermeldung erscheint ganz zu Recht -- T ist unbekannt. Du musst den Vergleich-Typ IComparer<T> schließen ("instantiieren"), an der Stelle handelt es sich nicht mehr um einen offenen Typ.
|
Re: Von TObjectList<T> erben?
Vielleicht so?
Delphi-Quellcode:
Da TNonFoodList nicht mehr generisch ist, kann mann den Platzhalter T auch nicht mehr verwenden, sondern muss ihn durch einen bekannten Typ ersetzen.
constructor TNonFoodList.Create(const AComparer: IComparer<TNonFood>; AOwnsObjects: Boolean);
|
Re: Von TObjectList<T> erben?
Der Hinweis von Uwe hats gebracht. :thumb:
|
Re: Von TObjectList<T> erben?
Hey, warum ist eigenlich nie alles mal richtig vieles etwas versteckt dokumentiert?
Delphi-Quellcode:
Bis auf die Prozedur geht alles in Delphi. :shock:
Type
TMyRecord<T> = Record X: T; Procedure Proc(P: T); End; TMyClass<T> = Class X: T; Procedure Proc(P: T); End; TMyInterfaceRecord<T> = Interface Procedure Proc(P: T); End; Procedure MyProc<T>(P: T); Begin End; zumindestens in Delphi 2010 ... anderes Versionen kann ich grade nicht testen. [add] In Delphi 2009 geht's auch und Turbo Delphi kennt noch keine Generics. |
Re: Von TObjectList<T> erben?
Zitat:
|
Re: Von TObjectList<T> erben?
Zitat:
Zitat:
![]() ![]() |
Re: Von TObjectList<T> erben?
Komisch mit ist so, als wenn ich sowas noch nie mit Records gesehn hatte.
(immer nur Klassen und Co.) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:41 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