AGB  ·  Datenschutz  ·  Impressum  







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

Klonen eines Interfaces

Ein Thema von Jasocul · begonnen am 22. Dez 2022 · letzter Beitrag vom 22. Dez 2022
Antwort Antwort
exon

Registriert seit: 12. Mär 2010
9 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#1

AW: Klonen eines Interfaces

  Alt 22. Dez 2022, 08:05
hm, zusätzliche Variable InCloning, also so:


Code:
   TMyClass = class(TInterfacedObject, IMyInt)
   strict private
                fA: Boolean;
                fB: String;
      fChanged: Boolean;
      fInCloning: Boolean;
   private
      procedure SetA(AValue: Boolean);
      function GetA: Boolean;
      function GetB: String;
   public
      constructor Create;
      destructor Destroy(); override;
      function Clone: IMyInt;
      function Save: Boolean;
      property A: Boolean read GetA write SetA;
      property B: String read GetB;
   end;
....
procedure TMyClass.SetA(AValue: Boolean);
begin
   if fA <> AValue then
   begin
      if not fInCloning then
        fChanged := True;
      fA := AValue;
   end;
end;

function TMyClass.Clone: IMyInt;
begin
   fInCloning := True;
   try
      <bisheriger Clone-Code>
   finally
     fInCloning := False;
   end;
end;
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.010 Beiträge
 
Delphi 2009 Professional
 
#2

AW: Klonen eines Interfaces

  Alt 22. Dez 2022, 08:23
Das hier sollte funktionieren:

Delphi-Quellcode:
function TMyClass.Clone: IMyInt;
var
  MyClass: TMyClass;
begin
  MyClass := TMyClass.Create;
  MyClass.fA := Self.fA;
  MyClass.fB := Self.fB;
  Result := MyClass
end;
(sehe dass die Lösung schon vorgeschlagen wurde - einziger Unterschied ist der "hard cast")

(siehe https://stackoverflow.com/a/8383009/80901)
Michael Justin
habarisoft.com
  Mit Zitat antworten Zitat
perpeto1234

Registriert seit: 16. Nov 2020
10 Beiträge
 
#3

AW: Klonen eines Interfaces

  Alt 22. Dez 2022, 08:24
Das hier sollte funktionieren:

Delphi-Quellcode:
function TMyClass.Clone: IMyInt;
var
  MyClass: TMyClass;
begin
  MyClass := TMyClass.Create;
  MyClass.fA := Self.fA;
  MyClass.fB := Self.fB;
  Result := MyClass
end;
(siehe https://stackoverflow.com/a/8383009/80901)
müsste aber "var MyClass: IMyInt" sein, sonst gibts Probleme mit der Referenzzählung, oder nicht?
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.010 Beiträge
 
Delphi 2009 Professional
 
#4

AW: Klonen eines Interfaces

  Alt 22. Dez 2022, 08:27
müsste aber "var MyClass: IMyInt" sein, sonst gibts Probleme mit der Referenzzählung, oder nicht?
Die Referenzzählung funktioniert auch bei diesem Konstrukt wie erwartet (automatische Freigabe, keine memory leaks).

Ein bekannter und berüchtigter Referenzzählungs-Bug entsteht, wenn man an einen Parameter, der einen Interfacetyp hat, eine frisch erzeugte Instanz übergibt:

Delphi-Quellcode:
procedure Machwas(MyInt: IMyInt);
...
...
...
MachWas(TMyClass.Create); // bad things will happen
Michael Justin

Geändert von mjustin (22. Dez 2022 um 08:32 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.371 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Klonen eines Interfaces

  Alt 22. Dez 2022, 08:30
Vielen Dank exon und perpeto1234.
Ich kann jetzt nicht sagen, welcher Vorschlag bei mir den Knoten hat platzen lassen, aber ich habe einen neuen Ansatz gefunden.
Es wird jetzt nicht über eine Clone-Funktion gemacht, die von der Quelle kommt, sondern eine Prozedure "CloneFrom" die als Parameter die Quelle bekommt. Dann kann ich auf alle vorhandenen Member-Variablen zugreifen und alles ohne Setter setzen.

@mjustin:
Deinen Ansatz werde ich mir merken. Der passt hier aber nicht ganz, da Quelle und Ziel als Instanzen bereits existieren.
Peter
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.010 Beiträge
 
Delphi 2009 Professional
 
#6

AW: Klonen eines Interfaces

  Alt 22. Dez 2022, 08:36
Deinen Ansatz werde ich mir merken. Der passt hier aber nicht ganz, da Quelle und Ziel als Instanzen bereits existieren.
Stimmt, nur dies sollte gehen, d.h. wenn nicht ein Interface sondern eine Instanz übergeben wird:

Delphi-Quellcode:
procedure TMyClass.CopyFrom(AOther: TMyClass);
begin
  Self.fA := AOther.fA;
  Self.fB := AOther.fB;
end;
Michael Justin
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.371 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Klonen eines Interfaces

  Alt 22. Dez 2022, 08:38
Im Prinzip ist das genau der Ansatz, den ich jetzt genommen habe. Das geht auch mit dem Interface als Parameter, wenn die Properties auch im Interface deklariert sind.
Peter
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Klonen eines Interfaces

  Alt 22. Dez 2022, 09:36
PS: Wenn es dir nur darum geht, dass es wie ein Interface/Objekt aussieht, also die Methoden und die Daten zusammen und die Funktionen in der "Klasse" drin,
dann kann man die einzelnen Funktionen auch als Methoden in den Record verschieben, statt einem Parameter auf Self zugreifen und fertig.

Bezüglich des Kopierens kannst dann diesen Record weiterhin genauso behandeln, wie bisher.




Ansonsten nimmt man im Allgemeinen eine Funktion, welche sich Delphi-Referenz durchsuchenTPersistent.Assign bzw. Delphi-Referenz durchsuchenTPersistent.AssignTo nennt.
Da drin mußt du dann die Property/Felder des einen Objekts in das andere Kopieren.

Beim normalen Assign mit allgemeinem Typen wird intern nochmals geprüft, ob der Typ passt,
aber hier kannst du einfach dem Parameter den richtigen Typen geben und schon kann nur der richtige Typ reingegeben werden.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (22. Dez 2022 um 09:41 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.371 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Klonen eines Interfaces

  Alt 22. Dez 2022, 10:36
PS: Wenn es dir nur darum geht, dass es wie ein Interface/Objekt aussieht, also die Methoden und die Daten zusammen und die Funktionen in der "Klasse" drin,
dann kann man die einzelnen Funktionen auch als Methoden in den Record verschieben, statt einem Parameter auf Self zugreifen und fertig.
Damit wird später noch deutlich mehr gemacht. Ein Record wird dann sicher nicht mehr ausreichend sein. Ansonsten gebe ich dir Recht.
Ansonsten nimmt man im Allgemeinen eine Funktion, welche sich Delphi-Referenz durchsuchenTPersistent.Assign bzw. Delphi-Referenz durchsuchenTPersistent.AssignTo nennt.
Da drin mußt du dann die Property/Felder des einen Objekts in das andere Kopieren.

Beim normalen Assign mit allgemeinem Typen wird intern nochmals geprüft, ob der Typ passt,
aber hier kannst du einfach dem Parameter den richtigen Typen geben und schon kann nur der richtige Typ reingegeben werden.
Mit Assign hatte ich es gestern auch versucht, bin dann aber irgendwie gescheitert (Die richtige Basisklasse habe ich dafür natürich genommen). Vermutlich war es gestern einfach schon zu spät und ich habe den Knoten nicht mehr aus den Gehirn bekommen. Ich lege mir aber gleich nochmal ein ToDo an, um das nochmal zu prüfen.

EDIT:
Ich bin nicht gescheitert, aber da die Instanzen vom Typ IMyInt sind, hätte ich hart auf TMyClass casten müssen, damit das assign funktioniert. Da ich kein Freund von solchen Casts bin, habe ich nach einer anderen Lösung gesucht. Wenn es einen Weg ohne den Cast gibt, bräuchte ich einen Tipp.
Peter

Geändert von Jasocul (22. Dez 2022 um 10:49 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Klonen eines Interfaces

  Alt 22. Dez 2022, 12:04
Ja, die vordefinierten Assign nehmen nur persistente Klassen an.
seit paar Jahren kann man in Delphi Interfaces (in denen ein Delphi-Objekt steckt) ganz einfach mit AS in ein Objekt casten.

Wenn alles Kopierbare aber als Property/Funktionen lesbar und schreibbar ist, kannst du auch einfach diese Property/Funktionen des Interfaces zum Kopieren der Eigenschaften benutzen und mußt nicht casten.



Wie gesagt, DU mußt die Eigenschafften einzeln übertragen, auch wenn man es bei persistenten Klassen auch anders lösen könnte.
Diese persistenten Klassen haben ja Funktionen, um ihren Inhalt/Zustand zu serialisieren/speichern, also quasi die eine Instanz in einen Stream speichern und die andere Instanz aus dem Stream zu laden.

Aber da du ja nicht von TPersistent oder TComponent geerbt hast, mußt du eh diese Methode selber komplett neu einbauen und kannst dort auch so Einiges ändern, wie eben z.B. den Parameter als Interface.

Im Prinzip ist es egal, wie du deine Kopieren-Methode nennst, aber es macht sich besser, wenn man Methoden mit einheitlichem Verhalten auch einheitlich benennt.
Darum Assign, aber auch Clone wird da oft als Name genommen. Wobei Assign die Daten in die eigene Instanz übernimmt, AssignTo an die andere Instanz übergibt und Clone erstellt selber die neue Instanz, überträgt die Eigenschaften und gibt es als Result zurück.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (22. Dez 2022 um 12:20 Uhr)
  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 08:05 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz