AGB  ·  Datenschutz  ·  Impressum  







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

TStrings und Assign

Ein Thema von Neutral General · begonnen am 17. Jun 2014 · letzter Beitrag vom 17. Jun 2014
Antwort Antwort
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#1

TStrings und Assign

  Alt 17. Jun 2014, 13:28
Hallo,

In TPersistent ist Assign so implementiert:

Delphi-Quellcode:
procedure TPersistent.Assign(Source: TPersistent);
begin
  if Source <> nil then Source.AssignTo(Self) else AssignError(nil);
end;
Ist es also nicht generell so gedacht dass AssignTo von den Nachfahren überschrieben wird?
So kann die Quelle entscheiden wie sie sich dem Zielobjekt zuweist.

TStrings hat aber jetzt direkt Assign überschrieben und ruft inherited Assign quasi nicht mal auf (es sein denn Source wurde nicht von TStrings abgeleitet, aber das kommt wohl sowieso eher selten bis gar nicht vor).

Jetzt stehe ich da mit meiner eigenen Ableitung von TStrings und möchte bestimmen wie eine TStringlist meine Klasse assignen soll und wollte dazu AssignTo überschreiben, aber das wird natürlich jetzt nie aufgerufen und ich hab verloren.

Ist das wirklich so gewollt?
In meinen Augen ist das ein Fehler..
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#2

AW: TStrings und Assign

  Alt 17. Jun 2014, 14:19
Ich vermute mal, es ist by-design. Wenn eine von TPersistent abgeleitete Klasse keine eigene Implementierung von Assign hat, dann und nur dann wird die Source-Instanz über AssignTo mit der Zuweisung beauftragt. Da TStrings und seine Abkömmlingen aber ein eigenes Assign implementieren, ist AssignTo hier aus dem Rennen. Würde TStrings im Assign nach der Zuweisung noch inherited aufrufen, käme ja zusätzlich noch das AssignTo der Source-Instanz zum tragen und nicht alternativ.

Wenn du nun einen eigenen Abkömmling von TStrings schreibst, dann wirkt sich deine Implementierung von AssignTo allenfalls für Zielklassen aus, die nicht von TStrings abgeleitet sind und kein eigenes Assign bereitstellen, was deine Klasse berücksichtigt. Willst du eine spezielle Behandlung bei einer Zuweisung deiner Klasse nach TStringList, die von dem Standardverhalten abweicht, dann ist der bestehende Mechanismus von Assign einfach nicht der richtige Weg. Da wäre dann eine separate Methode á la AssignToStringList in deiner Klasse und ein Aufruf dieser an den entsprechenden Stellen wohl der bessere Weg. Vielleicht kannst du auch die Inheritance von TStrings aufbrechen, dann käme dein AssignTo wieder zum tragen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

AW: TStrings und Assign

  Alt 17. Jun 2014, 14:35
Ja gut, dass nicht ein implementiertes Assign UND das AssignTo aufgerufen werden (sollen) ist klar.
Ich bin nur davon ausgegangen dass das Überschreiben von AssignTo das Standardverfahren wäre.

Ein AssignToStringlist bringt mir in meine Fall leider nichts weil mein Problem das Assign einer Stringliste im VCL-Code ist, den ich leider nicht grad auf AssignToStringlist umbauen kann

Naja dann muss ich mir irgendwie was schlaues überlegen
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.016 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#4

AW: TStrings und Assign

  Alt 17. Jun 2014, 16:53
Jetzt stehe ich da mit meiner eigenen Ableitung von TStrings und möchte bestimmen wie eine TStringlist meine Klasse assignen soll und wollte dazu AssignTo überschreiben, aber das wird natürlich jetzt nie aufgerufen und ich hab verloren.
Soll das heißen, deine Ableitung ist nicht kompatibel mit der TStrings.Assign Methode?
Wenn ja, warum? Hört sich ein bisschen wie eine Verletzung des LSP an, sollte es so sein.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#5

AW: TStrings und Assign

  Alt 17. Jun 2014, 17:09
Das konkrete Problem ist:

Habe meine eigene Items-Klasse für meine Combobox (letztendlich von TStrings abgeleitet) und diese beinhaltet Werte die TStrings oder TStringlist nicht beinhaltet oder kennt.

Beim erstellen der Combobox (CreateWnd, DestroyWnd) wird (aus welchen Gründen auch immer) eine Sicherheitskopie der Items in eine TStringlist (TCustomComboBox.FSaveItems) gespeichert (per Assign) wodurch meine zusätzlichen Infos natürlich nicht mit in diese TStringlist übertragen werden. Später wird diese Sicherung der Items wieder zurückgespielt und dadurch gehen die in meiner Items-Klasse enthaltenen zusätzlichen Informationen verloren.

Da wollte ich mit einem überschriebenen AssignTo in meiner Items-Klasse den TStringlist-Fall abfangen und dafür sorgen dass die Daten mit rüberkommen.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: TStrings und Assign

  Alt 17. Jun 2014, 17:17
Dann wäre es vielleicht besser nicht von TStrings sonder von TList oder TObjectList abzuleiten?
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#7

AW: TStrings und Assign

  Alt 17. Jun 2014, 17:25
Wo sind denn deine Zusatzdaten drin?

Wenn am TStrings.Objects, dann brauchst du nur dafür zu sorgen, daß die beiden TStrings-Nachfahren einen Speicherplatz für Objects beinhalten, denn das wird automatisch umkopiert, beim Assign.

Nur haben nicht alle TStrings-Nachfahren sowas. (z.B. das TMemoStrings im TMemo)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: TStrings und Assign

  Alt 17. Jun 2014, 18:19
TPersistent.Assign bzw. TPersistent.AssignTo machen nichts außer Fehlermeldungen anzuzeigen. Weshalb es diese Implentierung überhaupt gibt hab ich noch nie verstanden? TStrings.Assign ruft TPersistent.Assign auf wenn Source <> TStrings ist. TStrings hat kein AssignTo. Deine Klasse braucht deshalb ein eigenes AssignTo oder mit TStrings.Assign arbeiten (falls möglich)?
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.016 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#9

AW: TStrings und Assign

  Alt 17. Jun 2014, 18:47
TPersistent.Assign bzw. TPersistent.AssignTo machen nichts außer Fehlermeldungen anzuzeigen. Weshalb es diese Implentierung überhaupt gibt hab ich noch nie verstanden? TStrings.Assign ruft TPersistent.Assign auf wenn Source <> TStrings ist. TStrings hat kein AssignTo. Deine Klasse braucht deshalb ein eigenes AssignTo oder mit TStrings.Assign arbeiten (falls möglich)?
Der Punkt ist, dass mit dem Überschreiben von Assign die Verwendung von AssignTo in Ableitungen verhindert wird, da sie ja nicht mehr aufgerufen wird wie in dem Fall von TStrings.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: TStrings und Assign

  Alt 17. Jun 2014, 21:09
TPersistent.Assign bzw. TPersistent.AssignTo machen nichts außer Fehlermeldungen anzuzeigen. Weshalb es diese Implentierung überhaupt gibt hab ich noch nie verstanden? TStrings.Assign ruft TPersistent.Assign auf wenn Source <> TStrings ist. TStrings hat kein AssignTo. Deine Klasse braucht deshalb ein eigenes AssignTo oder mit TStrings.Assign arbeiten (falls möglich)?
Das Delphi-Referenz durchsuchenTPersisten.Assign und Delphi-Referenz durchsuchenTPersistent.AssignTo ist ja nicht ausschließlich für Delphi-Referenz durchsuchenTStrings eingeführt worden, sondern auch um eigene Klassen zu implementieren.

Dann kommt zum besseren Verständnis hier mal eine Preisfrage:

Gegeben sind zwei Klassen in zwei getrennten Units:
Delphi-Quellcode:
unit Model_Person;

interface

uses
  Classes;

type
  TPerson = class( TPersistent )
  private
    FFirstname : string;
    FLastname : string;
    procedure AssignToPerson( Other : TPerson );
  protected
    procedure AssignTo( Dest : TPersistent ); override;
  public
    constructor Create( const Firstname, Lastname : string );
  published
    property Firstname : string read FFirstname;
    property Lastname : string read FLastname;
  end;

implementation

{ TPerson }

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

procedure TPerson.AssignToPerson( Other : TPerson );
begin
  Other.FFirstname := Self.FFirstname;
  Other.FLastname := Self.FLastname;
end;

constructor TPerson.Create( const Firstname, Lastname : string );
begin
  inherited Create;
  FFirstname := Firstname;
  FLastname := Lastname;
end;

end.
und das entsprechende DatenTransferObjekt dazu
Delphi-Quellcode:
unit DTO_Person;

interface

uses
  Classes;

type
  TPerson_DTO = class( TPersistent )
  private
    FFirstname : string;
    FLastname : string;
    procedure AssignToPerson_DTO( Other : TPerson_DTO );
  protected
    procedure AssignTo( Dest : TPersistent ); override;
  published
    property Firstname : string read FFirstname write FFirstname;
    property Lastname : string read FLastname write FLastname;
  end;

implementation

{ TPerson_DTO }

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

procedure TPerson_DTO.AssignToPerson_DTO( Other : TPerson_DTO );
begin
  Other.FFirstname := Self.FFirstname;
  Other.FLastname := Self.FLastname;
end;

end.
Nun wollen wir folgendes erreichen
Delphi-Quellcode:
program dp_180780;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  Model_Person in 'Model_Person.pas',
  DTO_Person in 'DTO_Person.pas';

procedure Main;
var
  LPerson_DTO : TPerson_DTO;
  LPerson : TPerson;
begin
  LPerson := TPerson.Create( 'Peter', 'Lustig' );
  try
    LPerson_DTO := TPerson_DTO.Create;
    try
      LPerson_DTO.Assign( LPerson );
      LPerson_DTO.Firstname := 'Erwin';
      LPerson.Assign( LPerson_DTO );
    finally
      LPerson_DTO.Free;
    end;
  finally
    LPerson.Free;
  end;
end;

begin
  try
    Main;
  except
    on E : Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;

end.
Wie muss nun die Implementierung aussehen (ohne beide Klassen in eine Unit zu packen)?

Auflösung Model_Person.pas
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  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 03:08 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