Recent

Author Topic: Copying Objects  (Read 5220 times)

Weitentaaal

  • Hero Member
  • *****
  • Posts: 503
  • Weitental is a very beautiful garbage depot.
Copying Objects
« on: August 05, 2021, 01:47:17 pm »
Hello,

i have an Object wich the User can Edit (For Example change Position of object).
i create a Copy of my Object (wich i do wrong / with references, so i have the same Pointer twice ?!  %)) then continue with my Object by moving it. Later i check if Position is valid, if so then ok else reset Position to its latest (stored in Copy of Object). But my Copy is just refering to the Object like my original did so it wont make sense.

how do i do a Copy of an Object (would need a Deep Clone cuz there are some Propertys wich have selfdefined enums stored).

Here the Object i want to Clone. High Priority to Coords and Split:

Code: Pascal  [Select][+][-]
  1.  
  2. TElement = class(TObject)
  3.       private
  4.          fBtlNum: Integer;
  5.          fBtlArtNum: Integer;
  6.          fZLAL: Integer;
  7.          fMoved: TDirection;
  8.          fnextBtl: TElement;
  9.          fprevBtl: TElement;
  10.          fCoords: IntPoint;
  11.          fData: Integer;
  12.          {Hier wird "TDirection" verwendet um anzugeben auf welcher Seite sich die Teilung befindet
  13.          Hier wird ein Array verwendet da ein Bauteil mehrere Teilungen haben könnte (Beispiel:
  14.          U-Geräteaufbau --> Bei den Eck-Bauteilen müssten 2 teilungen möglich sein)}
  15.          fSplit: TSplit;
  16.       public
  17.          property BtlNum: Integer read fBtlNum write fBtlNum;
  18.          property BtlArtNum: Integer read fBtlArtNum write fBtlArtNum;
  19.          //Luftstrang: 0 = Zuluft ; 1 = Abluft
  20.          property ZLAL: Integer read fZLAL write fZLAL;
  21.          property Moved: TDirection read fMoved write fMoved;
  22.          property nextBtl: TElement read fnextBtl write fnextBtl;
  23.          property prevBtl: TElement read fprevBtl write fprevBtl;
  24.          property Data: Integer read fData write fData;
  25.          property Coords: IntPoint read fCoords write fCoords;
  26.          property Split : TSplit read fSplit write fSplit;
  27.          constructor Create();
  28.          destructor Destroy(); override;
  29.          procedure Remove();
  30.          procedure CopyTo(Element: TElement);
  31.          procedure SwapWith(Element: TElement);
  32.          procedure RemoveNextConn();
  33.          procedure RemovePrevConn();
  34.          procedure RemoveNextSplit();
  35.          procedure RemovePrevSplit();
  36.          procedure RemoveConnections();
  37.          function HasNextBtl(): Boolean;
  38.          function HasPrevBtl(): Boolean;
  39.          function IsOnNextBtl(BtlPos: IntPoint): Boolean;
  40.          function IsOnPrevBtl(BtlPos: IntPoint): Boolean;
  41.    end;
  42.  
  43.  


any Help would be appreciated :)

EDIT : i wrote my own Copy/Clone function (like Assign from TPersistent) just did not assign it correctly.

i can share my Code  if some1 else does need it.

Thanks :)
« Last Edit: August 05, 2021, 02:25:24 pm by Weitentaaal »
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.2

devEric69

  • Hero Member
  • *****
  • Posts: 648
Re: Copying Objects
« Reply #1 on: August 05, 2021, 02:28:21 pm »
how do i do a Copy of an Object (would need a Deep Clone cuz there are some Propertys wich have selfdefined enums stored).

Indeed, as you said, " deep-copy (clone) " pattern requires the use of json AFAIK, in order to serialize the object in text-flow\text-stream, and reserialize it, reify it cloned elsewhere, (  on the same room and same machine and the same program, or on the orbital station ;D ), if overriding the Assign method is "out of scope" (too much nested objects). That said, I don't have a source example, personally: sorry :-[ .
« Last Edit: August 05, 2021, 02:34:12 pm by devEric69 »
use: Linux 64 bits (Ubuntu 20.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

Weitentaaal

  • Hero Member
  • *****
  • Posts: 503
  • Weitental is a very beautiful garbage depot.
Re: Copying Objects
« Reply #2 on: August 06, 2021, 08:17:56 am »
Hi devEric69,

thanks for your Reply :)
"That said, I don't have a source example, personally: sorry" no Problem i solved the Problem.

Anyways i just had a very unclear opinion about Objects and missunderstood them. Better me now ;)
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.2

Weitentaaal

  • Hero Member
  • *****
  • Posts: 503
  • Weitental is a very beautiful garbage depot.
Re: Copying Objects
« Reply #3 on: August 06, 2021, 09:56:25 am »
New Question :

What if i have an Object wich Sores another Object (for Example Linked lists). how do i copy the "Neighbours" ?

Example:

Code: Pascal  [Select][+][-]
  1.  
  2. //input
  3. GetElement(Sel).DeepCopyTo(ElemBefore); //Works
  4. GetElement(Sel).nextBtl.DeepCopyTo(ElemBefore.nextBtl); //Not work
  5. GetElement(Sel).prevBtl.DeepCopyTo(ElemBefore.prevBtl); //Not work
  6.  
  7. //Output
  8. IF GetElement(m3D).nextBtl.Equals(ElemBefore.nextBtl) then begin
  9.    ShowMessage('Deep Copy did not Work'); //this message is shown
  10. end;
  11.  
  12. IF GetElement(m3D).Equals(ElemBefore) then begin
  13.    ShowMessage('Deep Copy did not Work'); //this message is NOT shown
  14. end;
  15.  
  16. //Copy Function
  17. procedure TElement.DeepCopyTo(Element :TElement);
  18. begin
  19.    Element.BtlNum := fBtlNum;
  20.    Element.BtlArtNum := fBtlArtNum;
  21.    Element.ZLAL := fZLAL;
  22.    Element.Moved := fMoved;
  23.    Element.prevBtl := fprevBtl;
  24.    Element.nextBtl := fnextBtl;
  25.    Element.Data := fData;
  26.    Element.Split:= fSplit;
  27.    Element.Coords := fCoords;
  28. end;
  29.  
  30.  


Did some Testing here are the Results :


###################################
COPY OF CURRENT(NOT CHANGED(Should) ) OBJECT ->
###################################
ElemBefore = <TELEMENT> = {

  <TOBJECT> = {

    _vptr$ = {
      0xc026c8,
      0x5}},

  FBTLNUM = 5,
  FBTLARTNUM = 0,
  FZLAL = 0,
  FMOVED = DIRNONE,

  FNEXTBTL = $a1e3dc8,
  FPREVBTL = $a1e1dc8,

  FCOORDS = {
    X = 15,
    Y = 3,
    Z = 0},

  FDATA = 0,
  FSPLIT = SPNEXT}

var
 ElemBefore: TElement =
class
(TObject)

###################################
CURRENT (CHANGED) OBJECT ->
###################################

TempElem = <TELEMENT> = {

  <TOBJECT> = {

    _vptr$ = {
      0xc026c8,
      0x5}},

  FBTLNUM = 5,
  FBTLARTNUM = 0,
  FZLAL = 0,
  FMOVED = DIRNONE,

  FNEXTBTL = $a1e3dc8,
  FPREVBTL = $a1e1dc8,

  FCOORDS = {
    X = 15,
    Y = 3,
    Z = 0},

  FDATA = 0,
  FSPLIT = SPNONE}

var
 TempElem: TElement =
class
(TObject)

#########

They still have the same adress ... can someone help/explain this to me ?
« Last Edit: August 06, 2021, 10:04:18 am by Weitentaaal »
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.2

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Copying Objects
« Reply #4 on: August 07, 2021, 01:18:51 am »
Why do you copy the values of (next/prev)Btl into the new object?
I expect the new copy to be dangling, not linked yet. So I can link it somewhere else.
Also, shouldn't the new copy have a different unique BtlNum?

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4458
  • I like bugs.
Re: Copying Objects
« Reply #5 on: August 07, 2021, 01:39:25 pm »
Indeed, as you said, " deep-copy (clone) " pattern requires the use of json AFAIK, in order to serialize the object in text-flow\text-stream, and reserialize it, reify it cloned elsewhere, (  on the same room and same machine and the same program, or on the orbital station ;D ), if overriding the Assign method is "out of scope" (too much nested objects).
No, a deep copy and serialization are 2 different things.
Pascal has no built-in deep copy syntax but the convention is to have an Assign() function.
If you have nested objects, then just call Assign() of those nested objects.
@Weitentaaal, you should also rename your deep-copy functions as Assign() because it is a well established convention. Remember to call inherited Assign if need be.
@jamie suggested RTTI. It has overhead and is mostly used for streaming. It allows to stream objects without knowing all their details. While doing a deep copy you know the details.
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

 

TinyPortal © 2005-2018