Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Komposition ähnlicher Objekte; Prozeduraufruf ohne "as ..." (https://www.delphipraxis.net/82083-komposition-aehnlicher-objekte%3B-prozeduraufruf-ohne.html)

LucasL 7. Dez 2006 21:37


Komposition ähnlicher Objekte; Prozeduraufruf ohne "as
 
Hallo,

ich würde gerne Objekte, die alle eine bestimmte Prozedur gemeinsam haben, in einer Liste zusammenstellen und dann diese gemeinsame Prozedur z.B. in einem Schleifendurchlauf aufrufen - ohne mich um den genauen Typ kümmern zu müssen. Geht das?

Ich habs mit ner abstrakten Klasse versucht, auf die die Liste zugreifen kann und die dann von allen Objekten implementiert wurde - ohne Erfolg :roll:.

Delphi-Quellcode:
  //----------
  // renderbares Objekt
  //----------
  TGLObject = class(TObject)
  private
    FNext : TGLObject;
  public
    constructor Create;

    procedure Render; virtual; abstract;
  end;

  //----------
  // Liste von renderbaren Objekten
  //----------
  TGLObjects = class(TObject)
  private
    FFirst,
    FPointer : TGLObject;
  public
    constructor Create;

    procedure Render;

    procedure Add(Obj: TGLObject);
    procedure Remove;
    [...]
  end;

  [...]

//----------
// Rendern aller in der Liste befindlichen Objekte
//----------
procedure TGLObjects.Render;
  var
    Obj: TGLObject;
begin
  Reset;
  while Fetch(Obj) do
    Obj.Render;
end;
Obj zeigt auf konkrete, von TGLObject abgeleitete Objekte, die "Render" implementiert haben. Der Compiler versucht jedoch in der while-Schleife der Prozedur Render von TGLObjects (-s!) die abstrakte Prozedur von TGLObject aufzurufen, da Obj ja eine TGLObject-Variable ist... Was aber natürlich zu einem Fehler führt.
Wie kann ich die Schleife simpel halten und trotzdem einen korrekten Prozeduraufruf erzeugen, ohne mich um den genauen Typen von dem jeweiligen Objekt kümmern zu müssen?

Vielen Dank und schönen Gruß,
Lucas

3_of_8 7. Dez 2006 21:46

Re: Komposition ähnlicher Objekte; Prozeduraufruf ohne "
 
Der Compiler greift immer auf die "frischeste" Methode zu. Das heißt er schaut bei dem Typen deiner Klasse nach, ob die Methode implementiert/überschrieben ist. Wenn ja, ruft er sie auf. Wenn nein, geht er eins höher in der Hierarchie. Das lässt sich nicht verhindern. Du kannst nur innerhalb der Methode mit inherited (Der Begriff inherited, nicht unser inherited) auf die vererbte Methode zugreifen.

Nennt sich dynamische Bindung oder so ähnlich.

EDIT: Genau, deshalb ist es egal ob du die Prozedur mit oder ohne as aufrufst. Der Compiler schaut beim Methodenaufruf in der Virtual Method Table nach, wie die Methoden deklariert sind, ein as bringt dabei also gar nichts.

LucasL 7. Dez 2006 22:22

Re: Komposition ähnlicher Objekte; Prozeduraufruf ohne "
 
Wie jetzt? Also ich habs mal mit "as" aufgerufen (alle Objekte waren noch vom gleichen abgeleiteten Typ), da lief alles glatt. Ohne "as" bekam ich einen "abstract error". Was habe ich wohl falsch gemacht?

Danke schonmal für deine schnelle Antwort.

mkinzler 7. Dez 2006 22:25

Re: Komposition ähnlicher Objekte; Prozeduraufruf ohne "
 
Du wirst nicht um einen Cast herumkommen (ob hart oder weich). den der Compiler weiß nicht, welches Objekt wirklich dahintersteckt und überprüft nur den Typ.

Meniskusschaden 7. Dez 2006 22:34

Re: Komposition ähnlicher Objekte; Prozeduraufruf ohne "
 
Zitat:

Zitat von LucasL
Wie jetzt? Also ich habs mal mit "as" aufgerufen (alle Objekte waren noch vom gleichen abgeleiteten Typ), da lief alles glatt. Ohne "as" bekam ich einen "abstract error". Was habe ich wohl falsch gemacht?

Danke schonmal für deine schnelle Antwort.

Funktioniert es, wenn Du die abgeleiteten Render-Methoden mit override deklarierst?

LucasL 7. Dez 2006 22:50

Re: Komposition ähnlicher Objekte; Prozeduraufruf ohne "
 
Du hast Recht :shock:, tausend Dank!

Für jeden zum testen und nachvollziehen (ohne "override" funktioniert es nicht):

Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TAbstract = class(TObject)
  public
    procedure Proc; virtual; abstract;
  end;

  TConcrete = class(TAbstract)
  public
    procedure Proc; override;
  end;

  procedure TConcrete.Proc;
  begin
    writeln('Konkret!');
  end;

var
  C: TAbstract;

begin
  { TODO -oUser -cConsole Main : Hier Code einfügen }
  C := TConcrete.Create;
  C.Proc;
  readln;
end.
Über die Hintergründe mache ich mir morgen einen Kopf ;).

Muetze1 7. Dez 2006 22:52

Re: Komposition ähnlicher Objekte; Prozeduraufruf ohne "
 
Abstract bedeutet, dass die Ableitung diese Methode implementieren muss. Du müsstest zuvor auch eine entsprechende Warnung/Hinweis vom Compiler bekommen haben. Ausserdem wird im Normalfall das Override nicht bei der Implementiereung sondern in der Typendeklaration in der Klasse angegeben.

LucasL 7. Dez 2006 23:00

Re: Komposition ähnlicher Objekte; Prozeduraufruf ohne "
 
Zitat:

Zitat von Muetze1
Abstract bedeutet, dass die Ableitung diese Methode implementieren muss. Du müsstest zuvor auch eine entsprechende Warnung/Hinweis vom Compiler bekommen haben.

Ich habe die Methode in der abgeleiteten Klasse doch implementiert?

Zitat:

Ausserdem wird im Normalfall das Override nicht bei der Implementiereung sondern in der Typendeklaration in der Klasse angegeben.
Ups, Tippfehler... Hab das override nach dem Test einfach an die falsche Stelle gesetzt.

Muetze1 8. Dez 2006 08:57

Re: Komposition ähnlicher Objekte; Prozeduraufruf ohne "
 
Zitat:

Zitat von LucasL
Zitat:

Zitat von Muetze1
Abstract bedeutet, dass die Ableitung diese Methode implementieren muss. Du müsstest zuvor auch eine entsprechende Warnung/Hinweis vom Compiler bekommen haben.

Ich habe die Methode in der abgeleiteten Klasse doch implementiert?

Mag ja sein, aber nach deinen Aussagen fehlte das Override. Und somit hast du sie nicht überschrieben und daraus würde folgendes folgen:

1. Du hast einen Compiler Hinweis bekommen, dass deine Methode xyz eine Methode der Klasse TVorfahr versteckt - und den Hinweis ignoriert hast.
2. Du die Methode zwar implementiert hast, aber neu implementiert hast. Du hast die Originalmethode versteckt, da du sie nicht überschrieben hast. Somit hast du die abstrakte Methode auch nicht implementiert sondern eine neue, davon unabhängige erstellt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:55 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