![]() |
arbeiten mit tobjectlist
hallo community,
ich habe nun mehrere klassen in einer tobjectlist gespeichert. jetzt will ich die procedure einer bestimmten instanz dieser objektliste aufrufen. gefunden habe ich bis jetzt tkiclass(kiobjectlist.last).aufrufaktki; (ist halt schon in mein cod umgeschrieben) oder mit items[index] arbeiten. letzteres funktioneirt aber wohl nicht bei dem aufruf einer methode - wie stelle ich es also an, dass von instanz nummer 3 eine bestimmte methode aufgerufen wird? grüße blinder007 |
AW: arbeiten mit tobjectlist
Wenn du ein Objekt aus einer Objektliste nimmst ist es sinnvoll das Objekt in einer lokalen Zwischenvariablen abzulegen.
Beispiel:
Delphi-Quellcode:
var
i : Integer; tmp_obj : TKiClass; begin for i:= 0 to objlist.Count-1 do begin tmp_obj := TKiClass(objlist.Items[i]); // jetzt kann man mit dem ausgelesenen Objekt arbeiten tmp_obj.AddEnergy(100); tmp_obj.RepairDamage; end; |
AW: arbeiten mit tobjectlist
... oder man nimmt gleich die generische TObjectList<T> ...
|
AW: arbeiten mit tobjectlist
Hätte ich spontan auch gesagt.
Zur eigentlichen Frage: Eigentlich geht es mit einem absoluten Index (z.B. 3) genau so wie du es momentan auch machst: Deine Methode "aufrufAktki()" rufst du ja folgendermaßen auf dem letzten Objekt in der Liste auf:
Delphi-Quellcode:
Wenn du nun das an Position drei haben möchtest, ändert sich ja nur das Last():
TKIClass(kiObjectList.Last()).aufrufAktki()
Delphi-Quellcode:
oder, als Alternative:
TKIClass(kiObjectList.Items[3]).aufrufAktki()
Delphi-Quellcode:
Wenn du statt einer einfachen
TKIClass(kiObjectList[3]).aufrufAktki()
Delphi-Quellcode:
eine
TObjectList
Delphi-Quellcode:
nimmst, wird es noch einiges kürzer:
TObjectList<TKIClass>
Delphi-Quellcode:
kiObjectList[3].aufrufAktki();
|
AW: arbeiten mit tobjectlist
Das 3. Item hat aber den Index 2 ;)
Index 3 zeigt auf das 4. Item |
AW: arbeiten mit tobjectlist
Ist das "dritte Item" nun das an "Position Drei" oder "Position Zwei"? Gibt es kein "nulltes Item" aber eins an "Position Null"? Was wenn man ein Array hat, das im Gegensatz zu einer Liste keine "Position Null" hat? Fragen über Fragen... :gruebel:
|
AW: arbeiten mit tobjectlist
Listen und dynamische Arrays sind grundsätzlich 0-indiziert, d.h. das erste Item hat den Index 0.
|
AW: arbeiten mit tobjectlist
Zitat:
Zitat:
Dann würde ich, ganz grob, so vorgehen:
Delphi-Quellcode:
Wobei ich hier einfach mal den "SoftCast"
if kiObjectList.Items[i] is TKIClass then
(kiObjectList.Items[i] as TKiClass).DoSomething; if kiObjectList.Items[i] is TPlayerClass then (kiObjectList.Items[i] as TPlayerClass).DoSomethingDifferent;
Delphi-Quellcode:
anstelle des HardCasts verwendet habe
as
Oder habe ich das Ganze wieder einmal falsch interpretiert und es sind mehrere Instanzen *einer* Klasse gemeint? |
AW: arbeiten mit tobjectlist
Zitat:
|
AW: arbeiten mit tobjectlist
Zitat:
|
AW: arbeiten mit tobjectlist
Aber warum sollte man überhaupt Instanzen mehrerer vollkommen verschiedener Klassen in eine einzige Liste packen wollen?
Auch stehe ich jetzt schon auf dem Schlauch, warum man sich den "as"-Cast sparen können soll? Was, wenn "DoSomethingDifferent" eben erst in der "TPlayerClass" deklariert worden ist? |
AW: arbeiten mit tobjectlist
Nicht das "as" sparen, sondern das "is", wenn man sowieso schon "as" verwendet. Da "as" die "is"-Prüfung intern vornimmt, ist die Verwendung beider zusammen doppelt gemoppelt.
|
AW: arbeiten mit tobjectlist
Zitat:
Delphi-Quellcode:
Der ist durch das if-is abgesichert.
if kiObjectList.Items[i] is TPlayerClass then
TPlayerClass(kiObjectList.Items[i]).DoSomethingDifferent; |
AW: arbeiten mit tobjectlist
Zitat:
Zitat:
|
AW: arbeiten mit tobjectlist
Du musst den letzten Nebensatz beachten.
|
AW: arbeiten mit tobjectlist
Zitat:
Wenn er wirklich unterschiedliche Klassen verwalten will, die als einzigen gemeinsamen Nachfahren TObject haben, dann ist TObjectList eine Wahl. In allen anderen Fällen bietet sich eine generische Liste über den BasisTyp an. Werden dann wirklich die einzelnen Klasseninstanzen gebraucht, ist eine Phalanx von
Delphi-Quellcode:
auch nicht wirklich elegant. Dafür gibt es besser geeignete Patterns (z.B.
if kiObjectList.Items[i] is <SomeClass> then
![]() Ich habe aber trotz der Original-Formulierung Zitat:
|
AW: arbeiten mit tobjectlist
hallo,
und ja, ich meinte mehrere instanzen ein und der selben klasse - für jede ki, die in diesem spiel auf tauchen soll eine instanz der klasse tkiclass. diese zahlreichen beiträge helfen mir schon sehr gut weiter und nebenbei habe ich noch was über is und as gelernt :) dank euch - nur zum schluss: sind die generischen tobjectlisten auch schon in delphi 6 implementiert? grüße blinder007 edit: dann habe ich es also richtig verstanden, dass ich am besten alle instanzen in lokale objekte lade, dann damit arbeite und sie am ende wieder freigebe? wenn das so ist, wie kann ich denn dan die änderung eines feldes in speichern. ich habe z.b. das feld fkiposition: tpointer; wie kann ich denn dann die lokale modifizierung dieses feldes wieder in der, aus ihrer ursprünglichen instanz, wieder dort speichern? |
AW: arbeiten mit tobjectlist
Generics und damit auch generische Listen gibt es erst ab Delphi 2009.
|
AW: arbeiten mit tobjectlist
Noch ein Tip zur Güte: Benutze Groß- und Kleinschreibung. Gewöhn dich am besten gleich jetzt daran.
Zum einen ist das in einem Forum guter Ton, denn etliche Leute sehen so einen "allesinkleinundohnekommaundpunkt"-Posts nur kurz an und übergehen ihn dann. Es ist echt mühsam, so ein Konglomerat aus Zeichen zu entziffern. Gib dir gefälligst Mühe, deine Frage lesbar und verständlich zu formulieren - du erwartest schließlich von uns, das wir uns gefälligst dieselbe Mühe geben, dich in die richtige Richtung zu schubsen und dir bei der Problemlösung zu helfen :-D Das gilt auch für Quelltexte. Die sind enorm viel lesbarer, wenn man sich an die Groß-Kleinschrift-Konventionen hält. Das mag in einem 30-Zeiler, wie du sie z.Zt. noch produzierst, gehen. Wenn es mal 30k oder 300k Zeilen sind (geht wesentlich schneller als man denkt), sieht das anders aus. Besonders, wenn man selbst (oder noch schlimmer: Ein Kollege) nach 6 Monaten einen Bug suchen muß ;) Ich meins nich böse, also nix für ungut :thumb: |
AW: arbeiten mit tobjectlist
Zum Schluss dann jetzt noch eine Frage.
Angenommen ich habe eine Instanz aus meiner TObjectlist bestimmt und es in ein lokales Objekt geladen. Nun hat diese Instanz auch Felder, die ich nun lokal auch verändere. Diese Änderungen will ich nun der Ursprungsinstanz wieder zuführen. Reicht dort eine einfache Zuweisung und dann das freigeben des lokalen objekts oder führt das zu fehlern? grüße blinder007 |
AW: arbeiten mit tobjectlist
Zitat:
|
AW: arbeiten mit tobjectlist
das bedeutet also, das erzeugen eines lokalen Objekts und die zuweisung bedeutet nur eine einfachere bedienbarkeit? sobald ich aber etwas an den gespeicherten Informationen verändere, ist es egal, von wo aus ich darauf zugreife oder sie verändere?
wenn ich also die lokale instanz erzeugt habe, jetzt den wert eines feldes verändere, die lokale instanz freigebe, hat sich der wert im speicher verändert und ich greife auch auf diesen veränderten Wert zurück, wenn ich ihn abfrage. ist das richtig verstanden? :) |
AW: arbeiten mit tobjectlist
Erzeugst Du eine lokale Instanz, oder weist Du lediglich die bereits vorhandene aus der Liste einer lokalen Variablen zu?
|
AW: arbeiten mit tobjectlist
Zitat:
|
AW: arbeiten mit tobjectlist
Das "Zwischenspeichern" des Verweises auf dein Objekt in der Liste bedeutet nicht nur Vereinfachung/Bequemlichkeit, sondern auch Performance.
Stell dir vor, du willst fünf Dinge mit deinem gesuchten Objekt tun. Würdest du (z.B. mittels Index 3) fünf mal das Objekt in der Liste "suchen" vergeht deutlich mehr Zeit als es einmal zu suchen, sich dann aufzuschreiben, wo es ist und dann die fünf Dinge zu tun. |
AW: arbeiten mit tobjectlist
Ich glaube, hier hat jemand das Zeiger-Problem, das schon so unendlich viele Programmierer in den Wahnsinn getrieben hat.
Folgender Code
Delphi-Quellcode:
weist eigentlich den Compiler an, sich ein Stück speicher zu holen (zu reservieren). Das Stück Speicher ist groß genug, das alle Felder und Methoden in diese Stück hineinpassen. Nehmen wir an, der Speicherblock hat die Adresse $00001234.
TMO:=TMyObject.Create;
In der Variablen TMO wird nun nur dieses $00001234 gespeichert. Nun stopfst du das frisch erzeugte TMO in eine TObjectList. TObjectList wiederum vermerkt in seiner Liste an gespeicherten Objekten nicht das Objekt selbst, sondern eben nur dieses $00001234. Holst du das Objekt aus der TObjectList wieder heraus (z.B. mit
Delphi-Quellcode:
) dann landet in TMO2 auch wieder nur das $00001234.
TMO2:=TObjectList[i] as TMyObject
Da nun zwei Variablen (TMO und TMO2) auf denselben Speicherbereich zeigen (Instanzvariablen sind tatsächlich nix anderes als Zeiger !) ist eine Änderung der Felder in TMO2 auch sofort in TMO zu sehen. Sind ja im Endeffekt beides dieselben Speicherbereiche, ergo die gleichen Instanzen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:03 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