Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Vererbung und klassenspezifische Methoden (https://www.delphipraxis.net/186297-vererbung-und-klassenspezifische-methoden.html)

SProske 21. Aug 2015 10:28

Vererbung und klassenspezifische Methoden
 
Ich habe eine Grundklasse, von der mehrere Klassen abgeleitet sind. Diese Grundklasse stellt einen Konstruktor zur Verfügung, um eine neue Instanz mit gleichen Eigenschaften zu erzeugen. Außerdem eine Methode um die Eigenschaften zu kopieren.

In der abgeleiteten Klasse verwende ich dann diesen Konstruktor.

Delphi-Quellcode:
interface

type

  TBaseClass = class
  strict protected
  public
    constructor CreateAsCopy(const aFrom: TBaseClass);virtual;
    procedure AssignProps(const aFrom: TBaseClass);virtual;
  end;

  TAdvancedClass = class(TBaseClass)
  strict protected
    FName: string;
  public
    property Name: string read FName write FName;

    procedure AssignProps(const aFrom: TBaseClass);override;
  end;

implementation


procedure TBaseClass.AssignProps(const aFrom: TBaseClass);
begin
  //
end;

constructor TBaseClass.CreateAsCopy(const aFrom: TBaseClass);
begin
  AssignProps(aFrom);
end;

procedure TAdvancedClass.AssignProps(const aFrom: TBaseClass);
begin
  inherited AssignProps(aFrom);
  FName := TAdvancedClass(aFrom).Name;
end;

end.
Delphi-Quellcode:
var
  F1, F2: TAdvancedClass;
begin
  F1 := TAdvancedClass.Create;
  try
    F1.Name := 'Test';
    F2 := TAdvancedClass.CreateAsCopy(F1);
    try
      Writeln(F2.Name);
      ReadLn;
    finally
      F2.Free;
    end;
  finally
    F1.Free;
  end;
end.
Das funktioniert soweit, mir wird korrekterweise Test ausgegeben. Allerdings sind mir die expliziten Type-Casts in AssignProps ein Dorn im Auge. Lieber hätte ich es so:

Delphi-Quellcode:
TAdvancedClass = class(TBaseClass)
  strict protected
    FName: string;
  public
    property Name: string read FName write FName;

    procedure AssignProps(const aFrom: TAdvancedClass);reintroduce;
  end;

procedure TAdvancedClass.AssignProps(const aFrom: TAdvancedClass);
begin
  inherited AssignProps(aFrom);
  FName := aFrom.Name;
end;
Dann erhalte ich aber als Ausgabe nicht mehr 'Test', sondern einen Leerstring. Wie kann ich es so anpassen, dass in meiner abgeleiteten Klasse ein "AssignProps" zur Verfügung habe, dass auch mit dieser Klasse funktioniert - und nicht mit der Grundklasse und dann Type-Casts auf die abgeleitete?

PS: Die Überschrift gefällt mir selber nicht, etwas besseres ist mir aber auch nicht wirklich eingefallen.

Sir Rufo 21. Aug 2015 10:46

AW: Vererbung und klassenspezifische Methoden
 
Schau dir einmal die Klasse Delphi-Referenz durchsuchenTPersistent an, die bringt die Methoden Delphi-Referenz durchsuchenTPersistent.Assign und Delphi-Referenz durchsuchenTPersistent.AssignTo mit, die schon fast das machen was du erreichen möchtest.

Allerdings wirst du um die Typecasts nicht herumkommen ;)

Sir Rufo 21. Aug 2015 11:10

AW: Vererbung und klassenspezifische Methoden
 
Und hier ein kleines Beispiel für die Verwendung von Delphi-Referenz durchsuchenTPersistent
Delphi-Quellcode:
unit Unit2;

interface

uses
  System.Classes;

type
  TFoo = class abstract( TPersistent )
  protected
    procedure AssignTo( Dest: TPersistent ); override;
  public
    constructor Create( );
    constructor CreateFrom( Other: TFoo );
  end;

  TAdvancedFoo = class( TFoo )
  private
    FFirstName: string;
    procedure AssignTo( Other: TAdvancedFoo ); overload;
  protected
    procedure AssignTo( Dest: TPersistent ); overload; override;
  public
    property FirstName: string read FFirstName write FFirstName;
  end;

  TMoreAdvancedFoo = class( TAdvancedFoo )
  private
    FLastName: string;
    procedure AssignTo( Other: TMoreAdvancedFoo ); overload;
  protected
    procedure AssignTo( Dest: TPersistent ); overload; override;
  public
    property LastName: string read FLastName write FLastName;
  end;

implementation

{ TFoo }

procedure TFoo.AssignTo( Dest: TPersistent );
begin
  if Dest is TFoo
  then
  else
    inherited;
end;

constructor TFoo.Create;
begin
  inherited;
end;

constructor TFoo.CreateFrom( Other: TFoo );
begin
  Create;
  Self.Assign( Other );
end;

{ TAdvancedFoo }

procedure TAdvancedFoo.AssignTo( Dest: TPersistent );
begin
  inherited;
  if Dest is TAdvancedFoo
  then
    AssignTo( Dest as TAdvancedFoo );
end;

procedure TAdvancedFoo.AssignTo( Other: TAdvancedFoo );
begin
  Other.FFirstName := Self.FFirstName;
end;

{ TMoreAdvancedFoo }

procedure TMoreAdvancedFoo.AssignTo( Other: TMoreAdvancedFoo );
begin
  Other.FLastName := Self.FLastName;
end;

procedure TMoreAdvancedFoo.AssignTo( Dest: TPersistent );
begin
  inherited;
  if Dest is TMoreAdvancedFoo
  then
    AssignTo( Dest as TMoreAdvancedFoo );
end;

end.

SProske 21. Aug 2015 11:52

AW: Vererbung und klassenspezifische Methoden
 
Gerade das Vermeiden der Typecasts war eigentlich der für mich relevante Punkt - wenn das sich nicht umgehen lässt, bleibt es eben so.

TPersistent ist interessant, danke für den Beispielcode - bringt mir im aktuellen Fall (einer bestehenden Anwendung, in der die Problematik ziemlich exzessiv zum Einsatz kommt) aber leider keinen echten Mehrwert. Vielleicht für neue Projekte...


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