![]() |
Property als Array
Hi!
Ich habe ein kleines Problem... und zwar will ich eine Property als Array verwenden. Ich hab es so versucht:
Delphi-Quellcode:
fOperators ist dabei ein array of string. Ich bekomm dann jedoch den Fehler "inkompatible Typen: 'dynamic Array' und 'Procedure'".
property Operators[Ndx: integer]: String read fOperators write fOperators;
Ich hab auch versucht, den Index von der Property wegzulassen. Ändert jedoch nichts... Aus der Fehlermeldung schließe ich, dass ich die Get- und Set-Methode mit einer Prozedur ausführen muss... Aber wie genau funktioniert das ganze dann? :gruebel: |
Re: Property als Array
|
Re: Property als Array
Schreib doch einfach
Delphi-Quellcode:
und drück Strg + Shift + C, dann macht Delphi schon die halbe Arbeit :wink: .
property Operators[Ndx: integer]: String read GetOperators write SetOperators;
|
Re: Property als Array
Um ein Item des Array zu bekommen, greifst du einfach über die getMethode darauf zu:
Delphi-Quellcode:
Analog bei der setMethode. Um ein neues Item hinzuzufügen brauchst du dann halt ne extra Methode.
function getArrayItem(Index : Integer) : String;
Begin //Bereichsprüfung nicht vergessen! if (Index > -1) and (Index < high(fArray)) Then result := fArray[Index]; else //Oder was auch immer, vielleicht sogar ne Exception,... result := ''; End; |
Re: Property als Array
Zitat:
Delphi-Quellcode:
heißen :gruebel: ?
if (Index > -1) and (Index <= High(fArray)) then
|
Re: Property als Array
Mein Code bis jetzt:
Delphi-Quellcode:
Ist das so richtig (bis auf den fehlenden Else-Zweig in der Set-Methode)? Und wie muss ich die Add-Methode implementieren? :gruebel:
type
TTokens = class private fOperators: array of string; function GetOperators(Index: integer): string; procedure SetOperators(Index: integer; s: string); public property Operators[Ndx: integer]: String read GetOperators write SetOperators; end; //... procedure TTokens.SetOperators(Index: integer; s: string); begin if Index < high(fOperators) then fOperators[Index] := s; end; function TTokens.GetOperators(Index: integer): string; begin if (Index > -1) and (Index <= high(fOperators)) Then result := fOperators[Index] else result := ''; end; |
Re: Property als Array
Nein, du prüft beim Setter wieder ein element zu wenig. mach am besten bei beidem < length () ;)
|
Re: Property als Array
@Khabarakh:
Jupp, das is mir durchgeflutscht ;) @malo: Bei ner Add-Methode mußt du einfach nur an das Array ein neues Element anhängen... |
Re: Property als Array
Zitat:
Wenn es eine array-basierte Liste sein soll sollte man sie stufenweise vergrößern. ;) Eine Vergrößerung auf 172% der alten Größe hat sich als bester Allroundwert gezeigt. Bei kleinen Datenmengen wäre es möglich den ersten Sprung relativ großzügig ausfallen zu lassen, dadurch würde man sich vielleicht kleine weitere Kopiererei antun müssen. Außerdem verstehe ich diese Liste von "Operatoren" nicht ganz... Eine Liste von Tokens könnte, um es ganz plain & easy zu machen, so aussehen:
Delphi-Quellcode:
type
TToken = class // was immer du damit machen willst ;-) end; TTokenClass = class of TToken;
Delphi-Quellcode:
Da Tlist seine Methoden nicht virtual deklariert hat, ist es nicht möglich diese zu überschreiben um auf den Typen zu testen. :?
type
TTokenListInherited = class(TObjectList) protected function getItem(aIndex: Integer): TToken; virtual; procedure setItem(aIndex: Integer; aToken: TToken); virtual; public function Add(aToken: TToken): Integer; virtual; function Remove(aToken: TToken): Integer; virtual; function IndexOf(aToken: TToken): Integer; virtual; function FindInstanceOf(aClass: TTokenClass; aExact: Boolean = True; aStartAt: Integer = 0): Integer; virtual; procedure Insert(aIndex: Integer; aToken: TToken); virtual; function First: TToken; virtual; function Last: TToken; virtual; property Items[Index: Integer]: TToken read getItem write setItem; default; end; implementation { TTokenListInherited } function TTokenListInherited.Add(aToken: TToken): Integer; begin Result := inherited Add(aToken); end; function TTokenListInherited.FindInstanceOf(aClass: TTokenClass; aExact: Boolean; aStartAt: Integer): Integer; begin Result := FindInstanceOf(aClass, aExact, aStartAt); end; function TTokenListInherited.First: TToken; begin Result := inherited First() as TToken; end; function TTokenListInherited.getItem(aIndex: Integer): TToken; begin Result := inherited GetItem(aIndex) as TToken; end; function TTokenListInherited.IndexOf(aToken: TToken): Integer; begin Result := inherited IndexOf(aToken); end; procedure TTokenListInherited.Insert(aIndex: Integer; aToken: TToken); begin inherited Insert(aIndex, aToken); end; function TTokenListInherited.Last: TToken; begin Result := inherited Last() as TToken; end; function TTokenListInherited.Remove(aToken: TToken): Integer; begin Result := inherited Remove(aToken); end; procedure TTokenListInherited.setItem(aIndex: Integer; aToken: TToken); begin inherited setItem(aIndex, aToken); end; Es ist also möglich, die Liste auf TObjectList oder einen Vorfahren zu casten und einfach etwas anderes als einen Nachfahren von TToken reinzuwerfen. Möglich wäre es also TObjectList zu verwenden anstatt davon abzuleiten. Dadurch kannst du dir sicher sein, dass nur TToken Instanzen in die InnerList gelangen können. Wie im oberen Beispiel ist keinerlei zusätzliche Logik nötig, da diese bereits von TList / TObjectList bereitgestellt wird. ;)
Delphi-Quellcode:
Der zweite Weg ist zwar gehörig hässlich aber hat nicht die Lücke des oberen. ;)
type
TObjectListClass = class of TObjectList; TTokenListNotInherited = class private fInnerList: TObjectList; protected property InnerList: TObjectList read fInnerList; function getItem(aIndex: Integer): TToken; virtual; procedure setItem(aIndex: Integer; aToken: TToken); virtual; public function Add(aToken: TToken): Integer; virtual; function Remove(aToken: TToken): Integer; virtual; function IndexOf(aToken: TToken): Integer; virtual; function FindInstanceOf(aClass: TTokenClass; aExact: Boolean = True; aStartAt: Integer = 0): Integer; virtual; procedure Insert(aIndex: Integer; aToken: TToken); virtual; function First: TToken; virtual; function Last: TToken; virtual; property Items[Index: Integer]: TToken read getItem write setItem; default; procedure Clear; virtual; constructor Create(); overload;virtual; constructor Create(aListClass :TObjectListClass); overload;virtual; end; implementation { TTokenListNotInherited } constructor TTokenListNotInherited.Create; begin fInnerList := TObjectList.Create(True); end; constructor TTokenListNotInherited.Create(aListClass :TObjectListClass); begin fInnerList := aListClass.Create(True); end; function TTokenListNotInherited.Add(aToken: TToken): Integer; begin Result := InnerList.Add(aToken); end; procedure TTokenListNotInherited.Clear; begin InnerList.Clear(); end; function TTokenListNotInherited.FindInstanceOf(aClass: TTokenClass; aExact: Boolean; aStartAt: Integer): Integer; begin Result := InnerList.FindInstanceOf(aClass, aExact, aStartAt); end; function TTokenListNotInherited.First: TToken; begin Result := InnerList.First() as TToken; end; function TTokenListNotInherited.getItem(aIndex: Integer): TToken; begin Result := InnerList[aIndex] as TToken; end; function TTokenListNotInherited.IndexOf(aToken: TToken): Integer; begin Result := InnerList.IndexOf(aToken); end; procedure TTokenListNotInherited.Insert(aIndex: Integer; aToken: TToken); begin InnerList.Insert(aIndex, aToken); end; function TTokenListNotInherited.Last: TToken; begin Result := InnerList.Last() as TToken; end; function TTokenListNotInherited.Remove(aToken: TToken): Integer; begin Result := InnerList.Remove(aToken); end; procedure TTokenListNotInherited.setItem(aIndex: Integer; aToken: TToken); begin InnerList[aIndex] := aToken; end; btw: TList suckz :P |
Re: Property als Array
:shock: Das ist ja ein ganz schöner Brocken...
Naja, manchmal kommt mir schon mal die bekannte Frage auf: Warum einfach, wenn es auch kompliziert geht? :gruebel: Meine "Liste von Operatoren" ist dafür da, dass man für meine "Programmiersprache" Operatoren hinzufügen bzw. prüfen kann. Das ganze hab ich gemacht, weil ich in diese Liste jeden Operator reinschreiben wollte, den es in dieser "Programmiersprache" geben sollte. Bei meinem Tokenizer sollte dann geprüft werden, ob das jeweilige Zeichen meines Sourcecodes ein Operator ist. Dafür die "Liste von Operatoren". Ich könnte natürlich auch eine Konstantenarray verwenden, aber ich weiß nicht, inwieweit ich meine Sprache noch erweitern will. Daher wollte ich ein variables Array nehmen. Und wegen der OOP wollte ich halt nicht unbedingt Public-Variablen verwenden, sondern lieber eine Property. Und ich gehe nicht für eine solch kleine Liste so große Umwege wie Robert mir vorschlagen will. Manches ist echt zu viel des Guten. Ich bin dir zwar sehr dankbar für deine Mühen, Robert, aber ich verstehe einfach nicht, wofür all das notwendig ist. Ich persöhnlich komme jederzeit auch gut mit einem einfachen Array klar. Wozu also eine TObjectList UND eine Klasse, in der die meisten (oder alle?) der ObjectList-Methoden drin vorkommen, die im Endeffekt nur die gleiche Methode einer echten TObjectList aufrufen. Ich halte sowas nicht nur für unnötig, sondern auch noch für Zeitverschwendung. Sorry, aber das musste einfach mal raus. Man muss nicht für ALLES eine eigene Klasse haben. |
Re: Property als Array
Das Ding hieß TTokens, deshalb dachte ich du packst dort deine Tokens rein.
Interessant wäre ab dem Punkt, wenn du unterschiedliche Tokenarten von TToken ableitest (Operatoren, Typen, Keywords,...). Und so kompliziert ist das gar nicht. ;) Es gibt doch Ctrl+Shift+C , effektiv habe ich an jeder Lister bestimmt weniger als 30 Zeilen getippt. Von denen ein Großteil der Buchstaben durch Code completion reingefumpt wurde. ;) Die Verwendung ist halt mega einfach und darum gates doch eigentlich, oder? :zwinker: Zitat:
Man darf das Wort Zeitverschwendung nicht so überstrapazieren. Es kostet wenige Minuten diese strong typed ObjectList zu tippen (wesentlich weniger Zeit als du für den letzten Absatz gebraucht hast :P ), aber bei jeder Verwendung sparst du dir Typecasts und ein paar Prüfungen. :zwinker: Verstehe mich nicht falsch, ich will dich hier in keine Ecke drängen. Ich hatte eigentlich nur das TTokens falsch interpretiert und nun musste ich einfach zur "Zeitverschwendung" Stellung nehmen... |
Re: Property als Array
Hi Robert!
Zitat:
Zitat:
Zitat:
Zitat:
Ich will ja nur Strings in der Liste speichern. Es würde also ein Array of String auch tun. Wofür also eine extra Klasse erstellen, wenn es auch leichter geht? Klar, um die ewigen SetLength's zu vermeiden könnte man noch eine Add-Methode implementieren, aber mehr ist ehrlich nicht nötig. Zitat:
Und ich gebe zu, die "Zeitverschwendung" scheint weniger Aufwand zu sein, als ich zuerst dachte. Ich bin dir natürlich sehr dankbar, wenn du dir nähere Gedanken zu meinem "Problem" machst und auch für Vorschläge offen. Aber manche Sachen halte ich einfach für unnötig und übertrieben. ;) |
Re: Property als Array
zur Ausgangsfrage - Wenn "fOperators" bereits ein Array of String ist wozu machst du dann noch die eckigen klammern bei deinem property?
Delphi-Quellcode:
Denn wenn fOperators bereits das Array ist hättest du ja sonst ein 2 dimensionales.
property Operators[Ndx: integer]: String read fOperators write fOperators;
am einfachsten ohne Get und SetMethode wäre es da doch
Delphi-Quellcode:
Type
TDynStringArr = Array of String; [...] private fOperators: TDynStringArr; [...] property Operators: TDynStringArr read fOperators write fOperators; |
Re: Property als Array
Zitat:
|
Re: Property als Array
Dazu eine Frage: Wieso kann ich nicht einfach
Delphi-Quellcode:
anstelle einer zusätzlichen (unnötigen?) property schreiben?
public
Operators: Array of String; |
Re: Property als Array
Zitat:
|
Re: Property als Array
Des Weiteren hast du bei einer Property die Möglichkeit zu überprüfen, ob der zugewiesene Wert auch in dein "Konzept" passt.
Soll heißen: Wenn deine Strings so aufgebaut werden müssen, dass der String IMMER mit "XYZ" beginnt, dann kannst du mit einer Array-Property da schon eingreifen und dir evtl. viel Schreibarbeit und Zeit bei der Fehlersuche sparen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:43 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