AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Richtige Objekt-Kopie? Aber wie?

Ein Thema von Kedariodakon · begonnen am 13. Feb 2007 · letzter Beitrag vom 15. Feb 2007
Antwort Antwort
Benutzerbild von Kedariodakon
Kedariodakon

Registriert seit: 10. Sep 2004
Ort: Mönchengladbach
833 Beiträge
 
Delphi 7 Enterprise
 
#1

Richtige Objekt-Kopie? Aber wie?

  Alt 13. Feb 2007, 16:00
Ok ich habe mal was ganz feines, wozu ich nicht gerade die passende Lösung parrat habe...

Ich habe verschiedene voneinander abgeleitete Klassen:

Delphi-Quellcode:
TParameterBase = Class
// ...
TParameter = Class( TParameterBase )
// ...
TParamererCollection = Class( TParameterBase )
// ...
TParameterCollectionList = Class( TParameterBase )
Von diesen Klassen gibt es, wer hätte es gedacht, weitere Ableitungen und dies verschieden tief...

Nun habe ich an einer Stelle ein Problem, dass ich eine Kopie eines Objekts benötige!

Als vorbereitende Maßnahme hab ich natürlich die Basisklasse "TParameterBase" mit einer virtuellen Assign-Methode versehen, welche auch fein durch alle Klassen gepflegt wurde.. =]

Problem ist aber, wie erzeuge ich ein Objekt einer Klasse, die ich im schlimmsten Fall nur über den "untersten" Vertreter "TParameterBase" kenne, um "Assign" aufzrufen?


Das dümmste was mir ATM einfällt, wäre die Basisklasse mit einer virtuellen "GetCopie" Methode auszustatten und diese überall nachzupflegen...
Nunja, ich halte diese Lösung aber für nicht so gut...

Eventuell hat ja jemand einen viel viel besseren Vorschlag...


Bye Christian
Christian
  Mit Zitat antworten Zitat
Benutzerbild von uligerhardt
uligerhardt

Registriert seit: 19. Aug 2004
Ort: Hof/Saale
1.735 Beiträge
 
Delphi 2007 Professional
 
#2

Re: Richtige Objekt-Kopie? Aber wie?

  Alt 13. Feb 2007, 16:17
Ich habe das für meine Kurven-Hierarchie mit Basisklasse TKurve so gelöst:
Delphi-Quellcode:
type
  TKurve = class(TPureInterfacedObject, IDrawable)
  private
    constructor CreateRaw; // nur fürs Klonen
    //...
  public
    //...
    function Clone: TKurve;
    procedure Assign(AKurve: TKurve); virtual;
    //...
  end;
Delphi-Quellcode:
constructor TKurve.CreateRaw;
begin
  inherited Create;
end;

function TKurve.Clone: TKurve;
type
  TKurvenClass = class of TKurve;
begin
  // Da der Konstruktor über ClassType aufgerufen wird (und nicht direkt
  // TKurve.CreateRaw), wird eine Instanz des richtigen Typs erzeugt:
  Result := TKurvenClass(ClassType).CreateRaw;
  Result.Assign(Self);
  Assert(Result.ClassType = ClassType);
end;
Vielleicht nützt dir das was.

Ciao, Uli.
Uli Gerhardt
  Mit Zitat antworten Zitat
Benutzerbild von Kedariodakon
Kedariodakon

Registriert seit: 10. Sep 2004
Ort: Mönchengladbach
833 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: Richtige Objekt-Kopie? Aber wie?

  Alt 14. Feb 2007, 14:12
hmm ein ClassType.Create sollte doch allein schon ausreichen oder? Ich werd es mal testen.

Bye Christian
Christian
  Mit Zitat antworten Zitat
Benutzerbild von uligerhardt
uligerhardt

Registriert seit: 19. Aug 2004
Ort: Hof/Saale
1.735 Beiträge
 
Delphi 2007 Professional
 
#4

Re: Richtige Objekt-Kopie? Aber wie?

  Alt 14. Feb 2007, 14:29
Zitat von Kedariodakon:
hmm ein ClassType.Create sollte doch allein schon ausreichen oder?
Öhm, da könntest du sogar recht haben.
Uli Gerhardt
  Mit Zitat antworten Zitat
Benutzerbild von Kedariodakon
Kedariodakon

Registriert seit: 10. Sep 2004
Ort: Mönchengladbach
833 Beiträge
 
Delphi 7 Enterprise
 
#5

Re: Richtige Objekt-Kopie? Aber wie?

  Alt 14. Feb 2007, 15:19
Hmm die Klasse wird zwar erstellt, aber scheinbar ohne das der Constructor aufgerufen wird...

Was schlussendlich dazu führt, dass an ein paar Stellen baba passsiert...

Bye Christian
Christian
  Mit Zitat antworten Zitat
Benutzerbild von uligerhardt
uligerhardt

Registriert seit: 19. Aug 2004
Ort: Hof/Saale
1.735 Beiträge
 
Delphi 2007 Professional
 
#6

Re: Richtige Objekt-Kopie? Aber wie?

  Alt 14. Feb 2007, 18:42
Bei nachfolgendem Testprojekt passiert bei mir kein Baba. (Wenn wir bei Baba an das Gleiche denken. )

CloneAssignTest.dpr:
Delphi-Quellcode:
program CloneAssignTest;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  CloneAssign in 'CloneAssign.pas';

var
  b1, b2: TBasis;

begin
  b1 := TAbgeleitetS.Create('StringDing', 'Blah');
  try
    b2 := b1.Clone;
    Writeln(b1.ToString);
    Writeln(b2.ToString);
  finally
    b1.Free;
  end;

  b1 := TAbgeleitetI.Create('IntDing', 4711);
  try
    b2 := b1.Clone;
    Writeln(b1.ToString);
    Writeln(b2.ToString);
  finally
    b1.Free;
  end;

  Readln;
end.
CloneAssign.pas:
Delphi-Quellcode:
unit CloneAssign;

interface

type
  TBasis = class
  strict private
    FName: string;
  public
    constructor Create(const AName: string);
    function Clone: TBasis;
    procedure Assign(Source: TBasis); virtual;
    function ToString: string; virtual;
  end;

  TAbgeleitetS = class(TBasis)
  strict private
    FText: string;
  public
    constructor Create(const AName, AText: string);
    procedure Assign(Source: TBasis); override;
    function ToString: string; override;
  end;

  TAbgeleitetI = class(TBasis)
  strict private
    FCount: Integer;
  public
    constructor Create(const AName: string; ACount: Integer);
    procedure Assign(Source: TBasis); override;
    function ToString: string; override;
  end;

implementation

uses
  SysUtils;
  
{ TBasis }

constructor TBasis.Create(const AName: string);
begin
  inherited Create;
  FName := AName;
end;

function TBasis.Clone: TBasis;
begin
  // Da der Konstruktor über ClassType aufgerufen wird (und nicht direkt
  // TBasis.CreateRaw), wird eine Instanz des richtigen Typs erzeugt:
  Result := TBasis(ClassType.Create);
  Assert(Result.ClassType = ClassType);
  Result.Assign(Self);
end;

procedure TBasis.Assign(Source: TBasis);
begin
  FName := Source.FName;
end;

function TBasis.ToString: string;
begin
  Result := FName + ': ' + ClassName;
end;

{ TAbgeleitetS }

constructor TAbgeleitetS.Create(const AName, AText: string);
begin
  inherited Create(AName);
  FText := AText;
end;

procedure TAbgeleitetS.Assign(Source: TBasis);
begin
  inherited Assign(Source);
  FText := TAbgeleitetS(Source).FText;
end;

function TAbgeleitetS.ToString: string;
begin
  Result := inherited ToString + sLineBreak + ' Text = "' + FText + '"';
end;

{ TAbgeleitetI }

constructor TAbgeleitetI.Create(const AName: string; ACount: Integer);
begin
  inherited Create(AName);
  FCount := ACount;
end;

procedure TAbgeleitetI.Assign(Source: TBasis);
begin
  inherited Assign(Source);
  FCount := TAbgeleitetI(Source).FCount;
end;

function TAbgeleitetI.ToString: string;
begin
  Result := inherited ToString + sLineBreak + ' Count = ' + IntToStr(FCount);
end;

end.
Haut das bei dir auch hin?
Uli Gerhardt
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#7

Re: Richtige Objekt-Kopie? Aber wie?

  Alt 14. Feb 2007, 18:43
Hallo ihr beiden,

am Code von Uli sticht mir der statische Konstruktor ins Auge. Um auf TParameterBase aufbauende Klassen in einer Factory einsetzen zu können ist der virtuelle Konstruktor mit gleichbleibender Signatur gefragt. Hier nur grob skizziert - die Übertragung auf eine Methode statt einer stand-alone function dürfte nicht schwer fallen:

Delphi-Quellcode:
type
  TParameterBase = class
  public
    constructor Create; virtual;
  end;

  TParameter = class(TParameterBase)
  public
    constructor Create; override;
  end;

  TParameterBaseClass = class of TParameterBase;


function Clone(p: TParameterBase): TParameterBase;
begin
  Result := TParameterBaseClass(p.ClassType).Create;
  Result.Assign(p);
end;
Dass der gewünschte Konstruktor bei Christians Versuch mit ClassType.Create nicht ausgeführt wird liegt daran, dass mit diesem Aufruf nur der statische Konstruktor von TObject errreicht wird. Das sollte im direkten Vergleich mit dem Code aus meiner Beispiel-Funktion klar werden.

Freundliche Grüße vom marabu
  Mit Zitat antworten Zitat
Benutzerbild von uligerhardt
uligerhardt

Registriert seit: 19. Aug 2004
Ort: Hof/Saale
1.735 Beiträge
 
Delphi 2007 Professional
 
#8

Re: Richtige Objekt-Kopie? Aber wie?

  Alt 14. Feb 2007, 20:09
Hallo, marabu!

Zitat von marabu:
am Code von Uli sticht mir der statische Konstruktor ins Auge. Um auf TParameterBase aufbauende Klassen in einer Factory einsetzen zu können ist der virtuelle Konstruktor mit gleichbleibender Signatur gefragt.
Den muss ich dann aber auch in jeder Ableitung überschreiben, wo er dann jedesmal exakt nichts macht - laaaangweilig!

Zitat von marabu:
Dass der gewünschte Konstruktor bei Christians Versuch mit ClassType.Create nicht ausgeführt wird liegt daran, dass mit diesem Aufruf nur der statische Konstruktor von TObject errreicht wird.
Klassenspezifische Initialisierung erledigt ja der Aufruf von Assign in TBasis.Clone. TObject.Create reicht also aus, solange ich ein "vernünftig" null-initialisiertes Objekt (also inkl. referenzgezählter Typen und so) des richtigen Typs kriege. Und das tut ClassType.Create auch bei statischem Konstruktor. (Oder genauer der Code, den der Compiler hinterrücks generiert, NewInstance oder _ClassCreate oder irgendsowas.) Anderenfalls würde das Assert(Result.ClassType = ClassType) fehlschlagen. Oder hab ich was übersehen?

Zugegebenermaßen kam mir mein Vorgehen am Anfang auch etwas wagemutig vor, aber es funktioniert seit einiger Zeit in einem realen Projekt.

Uli.
Uli Gerhardt
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#9

Re: Richtige Objekt-Kopie? Aber wie?

  Alt 15. Feb 2007, 06:12
Guten Morgen,

Zitat von uligerhardt:
... Den muss ich dann aber auch in jeder Ableitung überschreiben ...
egal wer dir das erzählt hat - er wollte dich leimen. Du musst nicht, aber du kannst.

Zitat von uligerhardt:
... Oder hab ich was übersehen? ...
Ich denke du hast das Wort Factory übersehen. Wenn dieses Konzept dich nicht interessiert, dann macht mein Beitrag für dich natürlich keinen Sinn. Christian wollte aber wissen, warum seine Konstruktoren nicht ausgeführt werden und das habe ich an Hand von deinem Code erklären wollen - no offense meant.

Freundliche Grüße
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:42 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