Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   TObjectList unterschiedliche Objekte erkennen? (https://www.delphipraxis.net/163966-tobjectlist-unterschiedliche-objekte-erkennen.html)

mcbain 24. Okt 2011 07:26

TObjectList unterschiedliche Objekte erkennen?
 
Hallo,
ich speichere in einer TObjectList unterschiedliche Objekte ab. Meine Frage lautet nun, wie kann ich beim auslesen der Objekte erkennen, um welches Objekt es sich handelt?

Die Objekte, welche ich in der List ablege, sind alle von einem anderen Objekt (TAuto) abgeleitet.
Ich habe folgendese probiert:

Code:
for i := 0 to ObjectList.Count - 1 do
begin
  Auto := TAuto(Result.Items[i]);

  if (Auto is TCabrio) then
     ShowMessage('Es ist ein Cabrio');

  if (Auto is TCoupe) then
     ShowMessage('Es ist ein Coupe');
end;
Funktioniert aber nicht.

Wäre nett, wenn mir jemand bitte helfen könnte. Bin wohl noch nicht ganz ausgeschlafen ;).
Vielen Dank.

DeddyH 24. Okt 2011 07:38

AW: TObjectList unterschiedliche Objekte erkennen?
 
Was bedeutet "funktioniert nicht"? Eigentlich sollte es, wenn ich nichts übersehen habe und die Daten auch wirklich stimmen.

Sir Rufo 24. Okt 2011 07:44

AW: TObjectList unterschiedliche Objekte erkennen?
 
Zitat:

Zitat von DeddyH (Beitrag 1132118)
Was bedeutet "funktioniert nicht"? Eigentlich sollte es, wenn ich nichts übersehen habe und die Daten auch wirklich stimmen.

Und ich würde sagen, dass ohne weiteren Code, das auch nicht funktioniert.
Delphi-Quellcode:
ObjectList
vs
Delphi-Quellcode:
Result
?

mcbain 24. Okt 2011 07:46

AW: TObjectList unterschiedliche Objekte erkennen?
 
Das heißt, dass er mir nicht erkennt, um welche Klasse es sich handelt. Obwohl ich in meine ObjectList ein TCabrio eingetragen habe, erkennt er mir hier

Code:
if (Auto is TCabrio) then
     ShowMessage('Es ist ein Cabrio');
nicht, dass es sich um ein TCabrio Objekt handelt.

@Sir Rufo: Sorry, das heißt natürlich nicht Result sondern Objectlist.

DeddyH 24. Okt 2011 07:47

AW: TObjectList unterschiedliche Objekte erkennen?
 
Na gut, so gesehen. Auf jeden Fall zu wenig Infos.

Lemmy 24. Okt 2011 07:51

AW: TObjectList unterschiedliche Objekte erkennen?
 
Zitat:

Zitat von mcbain (Beitrag 1132120)
Das heißt, dass er mir nicht erkennt, um welche Klasse es sich handelt. Obwohl ich in meine ObjectList ein TCabrio eingetragen habe, erkennt er mir hier

Code:
if (Auto is TCabrio) then
     ShowMessage('Es ist ein Cabrio');
nicht, dass es sich um ein TCabrio Objekt handelt.

Und was für eine Klasse hat dann das Objekt (Auto.ClassName)?

DeddyH 24. Okt 2011 07:57

AW: TObjectList unterschiedliche Objekte erkennen?
 
Und zeigen Result und ObjectList auf dasselbe Objekt? Diese Frage von Sir Rufo scheint das Entscheidende zu sein.

mcbain 24. Okt 2011 08:08

AW: TObjectList unterschiedliche Objekte erkennen?
 
Ok, ich versuche es beispielhaft zu erklären.
Habe folgende Klassen:

TAuto:
Code:
 TAuto = class(TObject)
      private    
        FHersteller: string;    

      published
        property Hersteller: string read FHersteller write FHersteller;
      end;
TCabrio:
Code:
 TCabrio = class(TAuto)
      private    
        FSitze: integer;    

      published
        property FSitze: string read FSitze write FSitze;
      end;
TCoupe:
Code:
 TCoupe= class(TAuto)
      private    
        FSitze: integer;    

      published
        property FSitze: string read FSitze write FSitze;
      end;

Nun speichere ich Objekte in meiner TObjectlist:
Code:
var: AutoListe: TObjectList;
     Cabrio: TCabrio;
     Coupe: TCoupe:
     Auto: TAuto;

 AutoListe := TObjectList.Create;
 Auto := TAuto.Create;
 Auto.FHersteller := 'BMW';

 Coupe:= TCoupe(Auto);
 Coupe.FSitze := 4;

 AutoListe.Add(Coupe);



 Auto := TAuto.Create;
 Auto.FHersteller := 'VW';

 Cabrio:= TCabrio(Auto);
 Cabrio.FSitze := 2;

 AutoListe.Add(Cabrio);
Und hier möchte ich auselesen, um welches Objekt es sich handelt:
Code:
for i := 0 to ObjectList.Count - 1 do
begin
  Auto := TAuto(ObjectList.Items[i]);

  if (Auto is TCabrio) then
     ShowMessage('Es ist ein Cabrio');

  if (Auto is TCoupe) then
     ShowMessage('Es ist ein Coupe');
end;
Aber es wird mir keine ShowMessage-Box erzeugt, somit erkennt er mir auch nicht mein Objekt.

webcss 24. Okt 2011 08:18

AW: TObjectList unterschiedliche Objekte erkennen?
 
Dein Problem liegt hier:
Zitat:

Zitat von mcbain (Beitrag 1132126)
Nun speichere ich Objekte in meiner TObjectlist:
Code:
...
 Auto := TAuto.Create;
 Auto.FHersteller := 'BMW';

 Coupe:= TCoupe(Auto);
 Coupe.FSitze := 4;

 AutoListe.Add(Coupe);

...

Du erzeugst ein TAuto und castest dann in eine Unterklasse, speicherst aber immer "nur" ein TAuto. Sollte eigentlich so heißen:
Delphi-Quellcode:
Coupe := TCoupe.Create;
Coupe.FHersteller := 'BMW';
Coupe.FSitze := 4;
AutoListe.Add(Coupe);
Dies ist beispielhaft für jede Unterklasse von TAuto. Dann funktioniert es auch mit
Delphi-Quellcode:
if Objectlist[i] is TCoupe then...

Andreas L. 24. Okt 2011 08:19

AW: TObjectList unterschiedliche Objekte erkennen?
 
Du erstellst die Objekte falsch. Versuch es mal so:
Delphi-Quellcode:
var: AutoListe: TObjectList;
     Cabrio: TCabrio;
     Coupe: TCoupe:
     Auto: TAuto;

 AutoListe := TObjectList.Create;

 Coupe:= TCoupe.Create;
 Coupe.Hersteller := 'BMW';
 Coupe.Sitze := 4;

 AutoListe.Add(Coupe);

 Cabrio := TCabrio.Create;
 Cabrio.Hersteller := 'VW';
 Cabrio.Sitze := 2;

 AutoListe.Add(Cabrio);

DerDan 24. Okt 2011 08:20

AW: TObjectList unterschiedliche Objekte erkennen?
 
Hallo,


Wenn du eine Object vom Typ Caprio tatsächlich mit Create erzeugen würdest, dann könnte dein Code schon funktionieren.
Aber aus irgenteinem Grund erzeugst du immer Auto und behauptest über einen Cast das es ein Caprio ist bevor du Werte zuweist.

das kann der is Operator aber niemals auflösen.

mfg

DerDan

ConnorMcLeod 24. Okt 2011 08:29

AW: TObjectList unterschiedliche Objekte erkennen?
 
Du castest ja das Auto nur als Cabrio. Sein tut's immer noch ein TAuto ...So wird ein Schuh draus:

Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
var
  AutoListe: TObjectList;
  Cabrio  : TCabrio;
  Coupe   : TCoupe;
  Auto    : TAuto;
  ListenAuto : TObject;
  i       : integer;
begin
  AutoListe := TObjectList.Create;
  Auto := TAuto.Create;
  Auto.FHersteller := 'BMW';

  Coupe:= TCoupe(Auto);
  Coupe.FSitze := 4;

  AutoListe.Add(Coupe);

  Auto := TAuto.Create;
  Auto.FHersteller := 'VW';

  Cabrio:= TCabrio.Create;
  Cabrio.FSitze := 2;

  AutoListe.Add(Cabrio);

  for i := 0 to AutoListe.Count - 1 do
  begin
    ListenAuto := AutoListe.Items[i];

    if (ListenAuto is TCabrio) then
    begin
       ShowMessage('Es ist ein Cabrio');
    end
    else if (ListenAuto is TCoupe) then
    begin
       ShowMessage('Es ist ein Coupe');
    end
    else
    begin
       ShowMessage(Auto.ClassName);
    end;
  end;
end;
Edit: ups, zu spät.

mcbain 24. Okt 2011 09:43

AW: TObjectList unterschiedliche Objekte erkennen?
 
Alles klar, vielen Dank für eure zahlreichen Antworten. So funktioniert es.
Wollte mir das belegen der Vater-Attribute immer sparen - da diese für jedes abgeleitete Kind ja immer gleich sind - und bin deshalb diesen Weg gegangen. Aber dann belege ich die Attribute halt für jedes Kind.

Vielen Dank nochmal
Gruß
mc

DeddyH 24. Okt 2011 09:48

AW: TObjectList unterschiedliche Objekte erkennen?
 
Musst Du doch gar nicht.

himitsu 24. Okt 2011 09:51

AW: TObjectList unterschiedliche Objekte erkennen?
 
Zitat:

Zitat von webcss (Beitrag 1132128)
Dein Problem liegt hier:
Zitat:

Zitat von mcbain (Beitrag 1132126)
Code:
...
 Auto := TAuto.Create;
 Auto.FHersteller := 'BMW';

 Coupe := TCoupe(Auto);
 Coupe.FSitze := 4;

 AutoListe.Add(Coupe);
...

Du erzeugst ein TAuto und castest dann in eine Unterklasse, speicherst aber immer "nur" ein TAuto. Sollte eigentlich so heißen:

Wenn du keine Ahnung vom Casten hast, bzw. es noch nicht richtig kannst/verstehst, dann verwende keine harten Casts ala
Delphi-Quellcode:
TCoupe(Auto)
,
sondern die weicheren Casts ala
Delphi-Quellcode:
(Auto as TCoupe)
, den so wäre dir das Problem sofort aufgefallen, weil es im Programm entsprechend geknallt hätte.

PS: Dein Pech war, daß der Zugriff auf das falsch gecastete Objekt nicht auch schon geknallt hatte, denn wenn FSitze erst in TCoupe deklariert wurde, dann gibt es dieses Feld in TAuto nicht, und somit greifst du auf etwas zu, was es nicht gibt, welches nicht unbedingt Gesund ist, für ein Programm.

r2c2 24. Okt 2011 14:28

AW: TObjectList unterschiedliche Objekte erkennen?
 
Die bessere Lösung für das Problem wäre wohl die Nutzung der Polymorphie:

- packe eine (abstrakte) virtuelle Methode in TAuto
- überschreibe die in den Subklassen
- und rufe die einfach mit nem cast auf TAuto (nicht auf die Subklassen) auf
==> keine Casts auf Subklassen nötig und vor allem keine explizite Typabfrage mit is...

Siehe auch: If Statement Considered Harmful

Und mal unabhängig vom konkreten Symptom sind das schon falsche Klassen. Neue Klassen sollte man nur erstellen, wenn diese neuen Klassen auch etwas neues können. Aber kann ein TCoupe mehr als ein TAuto? Oder ist das eigentlich nicht doch eher ein Attribut?


mfg

Christian


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:34 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz