Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Per Klasse auf übergeordnete Klasse zugreifen? (https://www.delphipraxis.net/63636-per-klasse-auf-uebergeordnete-klasse-zugreifen.html)

Pseudemys Nelsoni 21. Feb 2006 07:01


Per Klasse auf übergeordnete Klasse zugreifen?
 
Moin,

ich möchte eine Komponente schreiben und einzelne Properties Kategorisch ordnen, so dass es im Objekt-Inspektor beispielsweise so aussieht:

+Kategorie1
`- Property1
`- Property2
`- Property3
+Kategorie2
`- Property1
`- Property2
`- Property3

usw...

Um dies zu lösen muss ich ja für jede Kategorie eine Klasse schreiben, die die dazugehörigen Properties beinhaltet.
Das Problem ist jetzt, dass eines dieser Felder einer Kategorie auf ein Feld der Hauptklasse zugreifen muss, bloss kennt eine untergeordnete Klasse ja nicht seine übergeordnete. Ich könnte ja meine Hauptklasse vorwärsdeklarieren und ein Feld selbiger in meiner Kategorieklasse anlegen, wo die Hauptklasse im Constructor(?) der Unterklasse mittgeteilt wird...

Die Frage ist eigentlich, ob dies der richtige weg ist?

r2c2 21. Feb 2006 07:13

Re: Per Klasse auf übergeordnete Klasse zugreifen?
 
Hallo :hi:
ne andere Möglichkeit wären Events: OnPropertyChange oder sowas...

mfg

Christian

Elvis 21. Feb 2006 07:19

Re: Per Klasse auf übergeordnete Klasse zugreifen?
 
Zitat:

Zitat von Pseudemys Nelsoni
Ich könnte ja meine Hauptklasse vorwärsdeklarieren und ein Feld selbiger in meiner Kategorieklasse anlegen, wo die Hauptklasse im Constructor(?) der Unterklasse mittgeteilt wird...
Die Frage ist eigentlich, ob dies der richtige weg ist?

Da du dich mit Delphi für einen altmodischen Singlepass compiler entschieden hast dürfte sich die Frage schon selbst beantworten... ;)
Du kannst forward decl. benutzen. Du kannst auch all die anderen Tricks benutzen, um zu verhindern, dass deine Units irgendwann, aufgrund verschränkter Typen, 1.000 Zeilen haben (Gibt sogar Leute, die damit angeben so große Monster zu haben :lol: )

Du kannst hier mit Interfaces arbeiten, oder deiner Hauptklassse einen Vorgänger verpassen, der nur das enthält was du hier brauchst.

Zitat:

Das Problem ist jetzt, dass eines dieser Felder einer Kategorie auf ein Feld der Hauptklasse zugreifen muss, bloss kennt eine untergeordnete Klasse ja nicht seine übergeordnete.
Im Owner steht das was du suchst...

Pseudemys Nelsoni 21. Feb 2006 07:25

Re: Per Klasse auf übergeordnete Klasse zugreifen?
 
Moin christian,

vielleicht habe ich es schlecht ausgedrückt, aber ich meinte es so:

Ich habe eine Subklasse und eine Hauptklasse, die so aussehen:

Delphi-Quellcode:
TServer = class(TPersistent)
private
    function GetHost: string;
    procedure SetHost(const Host: string);
    function GetPort: Word;
    procedure SetPort(const Port: Word);
  published
    property Host: string read GetHost write SetHost;
    property Port: Word read GetPort write SetPort;
  end;

TMainClass = class(TComponent)
private
  FClientSocket: TClientSocket;
  FServer: TServer;
published
  Server: TServer read FServer write FServer;
end;
So... TServer ist eine Klasse für die "Kategorie" "Server" die man nachher im OI sehen kann mit seinen Membern "Host" und "Port"...
Die privaten Methoden dieser Klasse müssen irgendwie an die gleichnamigen Properties des Feldes "FClientSocket" der Hauptklasse kommen... nur wie? Ich finde meine obige Idee "unsauber".

Edit:

@Elvis: wie komme ich an den Owner? TPersistent muss man keinen übergeben....welche Klasse sollte ich stattdessen verwenden?

Jelly 21. Feb 2006 08:43

Re: Per Klasse auf übergeordnete Klasse zugreifen?
 
Zitat:

Zitat von Pseudemys Nelsoni
@Elvis: wie komme ich an den Owner? TPersistent muss man keinen übergeben....welche Klasse sollte ich stattdessen verwenden?

Ich bin zwar nicht Elvis aber kann vielleicht trotzdem helfen.
Du musst doch irgendwo in deiner MainClass dein TServer initialisieren, und das machst Du doch sicherlich etwa so im Constructor deiner MainClass:
Delphi-Quellcode:
constructor TMainClass.Create (AOwner : TComponent) ; override ;
begin
    FServer := TServer.Create ;
end ;
Wenn Du jetzt aber den constructor deiner TServer Klasse überlädst, und so definierst:
Delphi-Quellcode:
public
  constructor Create (AMainClass : TMainClass) ; overload ;
kannst du in der MainClass so ein Objet erzeugen:
Delphi-Quellcode:
constructor TMainClass.Create (AOwner : TComponent) ; override ;
begin
    FServer := TServer.Create (Self) ;
end ;
Diesen Parameter kannst Du nun auswerten und z.B. in einer private property speichern.

Elvis 21. Feb 2006 08:57

Re: Per Klasse auf übergeordnete Klasse zugreifen?
 
Delphi-Quellcode:
IMainDingens = interface
  function getPort : Word;
  function getHost : String;

  procedure setPort (const value : Word);
  procedure setHost (const value : String);
end;

Delphi-Quellcode:
TServer = class(TPersistent)
private
  fMainDingens : IMainDingens;
  ...
public
  constructor Create(const owner : IMainDingens)
end;

Die Implementierung des Interfaces in deiner Komponente solte straight forward sein. ;)
Du kannst die Getter/Setter dort auch als protected deklarieren, wodurch sie nicht ohne weiteres öffentlich veränderbar sind. ;)

@Jelly
Ich dachte seine Aggregate sind Komponenten, TPersistent hat keinen Owner, deshalb kann man ihn hier gleich auf das Interface typisieren und sich so type casts sparen. ;)

Pseudemys Nelsoni 21. Feb 2006 09:29

Re: Per Klasse auf übergeordnete Klasse zugreifen?
 
Moin :)

Besten Dank für eure Hilfe. ;)

@Elvis: WIeso ist es ein Interface und keine Klasse? (Nie mit solchen gearbeitet)

Elvis 21. Feb 2006 12:25

Re: Per Klasse auf übergeordnete Klasse zugreifen?
 
Zitat:

Zitat von Pseudemys Nelsoni
@Elvis: WIeso ist es ein Interface und keine Klasse? (Nie mit solchen gearbeitet)

Deine widerwillige Frage nach den Forward declarations ließ vermuten, dass du keinen Bock hast soviele Klassen in eine Unit zu quetschen.
Mit der Abstraktion über ein Interface kannst du die Verbindung zwischen den 2 Klassen in eine 3. Unit auslagern wodurch dein TServer keine Ahnung von der Hauptklasse haben muss. ;)
So hast du 3 Units, die jeweils auf einen Moni passen im Gegensatz zu ... :kotz:


Delphi-Quellcode:
type
   IMainDingens = interface
      function getPort : Integer;
      function getHost : string;

      procedure setPort(value : Integer);
      procedure setHost(value : string);

      property Port : Integer read getPort write setPort;
      property Host : string read getHost write setHost;
   end;
Delphi-Quellcode:
uses
   Classes,
   uMainComponentInterface;

type
   TServer = class(TPersistent)
   private
      fMainDingens : IMainDingens;
      function getHost : string;
      procedure setHost(const value : string);
      function getPort : Word;
      procedure setPort(const value : Word);
   published
      property Host : string read getHost write setHost;
      property Port : Word read getPort write setPort;
   public
      constructor Create(const owner : IMainDingens);
   end;
implementation

{ TServer }

constructor TServer.Create(const owner: IMainDingens);
begin
   fMainDingens := owner;
end;

function TServer.getHost: string;
begin
   result := fMainDingens.Host;
end;

function TServer.getPort: Word;
begin
   result := fMainDingens.Port;
end;

procedure TServer.setHost(const value : string);
begin
   fMainDingens.Host := value;
end;

procedure TServer.setPort(const value : Word);
begin
   fMainDingens.Port := value;
end;
Delphi-Quellcode:
uses
   Classes,
   ScktComp,
   uServerAggregate,
   uMainComponentInterface;

type
   TMainClass = class(TComponent, IMainDingens)
   private
      fClientSocket : TClientSocket;
      fServer : TServer;
   protected
      property ClientSocket : TClientSocket read fClientSocket implements IMainDingens;

      // vielen Dank dafür, dass man keine abstrakten Properties in Interfaces packen kann! :wall:
      function getPort : Integer;
      function getHost : string;
   published
      property Server : TServer read fServer write fServer;
   public
      procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
   end;
implementation

{ TMainClass }


function TMainClass.getHost: string;
begin
   Result := fClientSocket.Host;
end;

function TMainClass.getPort: Integer;
begin
   Result := fClientSocket.Port;
end;

procedure TMainClass.AfterConstruction;
begin
   inherited;
   fClientSocket := TClientSocket.Create(self);
   fServer := TServer.Create(self);
end;

procedure TMainClass.BeforeDestruction;
begin
   inherited;
   fServer.Free();
   fClientSocket.Free();
end;
Die beiden getter in der Komponente verdanken wir der zickigen Eigenart von Delphi-Interfaces, Properties nur mit vollen Zugriffsmethoden zuzulassen. (anstatt einfach property X : TType read write;)
Deshalb können die Getter hier nicht zu TClientSocket delegiert werden. :wall:

r2c2 21. Feb 2006 12:51

Re: Per Klasse auf übergeordnete Klasse zugreifen?
 
Die Frage scheint sich ja schon geklärt zu haben, trotzdem noch n alternativer Weg:

Delphi-Quellcode:
TMainClass = class(TComponent)
private
  FClientSocket: TClientSocket;
  FServer: TServer;
  procedure PropCh(<Parameter anpassen>); // Methode, die Socket-Properties anpasst
public
  constructor Create(owner...);
published
  Server: TServer read FServer write FServer;
end;

constructor TMainClass.Create(...);
begin
  inherited...;
  ...
  FServer = TServer.Create;
  FServer.OnPropertyChange = PropCh; // OnPropertyChange in Setter-Metghoden aufrufen; dadurch wird PropCh aufgerufen
end;

procedure ProbCh;
begin
  ... // ClientSocket ändern
end;
mfg

Christian


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