Recent

Author Topic: Copying Objects  (Read 4627 times)

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 272
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.6 x86_64-win64-win32/win64
FPC-Version: 3.0.4
Compiler Version: 3.2.0

devEric69

  • Hero Member
  • *****
  • Posts: 555
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

  • Sr. Member
  • ****
  • Posts: 272
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.6 x86_64-win64-win32/win64
FPC-Version: 3.0.4
Compiler Version: 3.2.0

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 272
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.6 x86_64-win64-win32/win64
FPC-Version: 3.0.4
Compiler Version: 3.2.0

engkin

  • Hero Member
  • *****
  • Posts: 2923
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?

jamie

  • Hero Member
  • *****
  • Posts: 4830
Re: Copying Objects
« Reply #5 on: August 07, 2021, 02:38:57 am »
if you place the needed items you need to duplication in a PUBLISHED section then you could simply create a new object of the same class and use the same code that is used when reading in the published properties..

 This is the RTTI information that a class can give you as long as it's in the published section.

I can't remember the name of the items now that there should be examples of reading and writing the published properties and with that you can obtains the whole set of values to be stored in a text stream to later be read back to a binary stream for which it assigns the properties etc.

 This is the same process that takes place when you start up your app , all the published properties get read from the resource of your EXE.
The only true wisdom is knowing you know nothing

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3959
  • I like bugs.
Re: Copying Objects
« Reply #6 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