Assign() vs AssignTo()

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Assign() vs AssignTo()

Graeme Geldenhuys-6
Hi,

In TPersistent, we have two virtual methods. Assign() which calls
AssignTo().

1) Why are they both virtual? It seems like Assign() is what I call a
template method, farming its work out to other helper methods - in this
case, AssignTo(). Normally template methods are not virtual, but their
helper methods (the ones doing the actual work) are. So again, why is
Assign() virtual?

2) Now seeing that both are virtual, and that is probably not going to
change in the RTL, which method is the preferred method to override so
you have the ability to do MyObject.Assign(MySource)? I've been
overriding Assign(), but thinking that maybe I should have overridden
AssignTo() instead.


ps:
The FPC (pdf) documentation for TPersistent.Assign() has a "See Also"
reference to TPersistent.AssignTo(). But that link doesn't work, because
AssignTo is Protected, and the RTL documentation doesn't include
Protected methods.


Regards,
  - Graeme -

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assign() vs AssignTo()

Andreas Schneider-7
Am 2016-02-11 16:13, schrieb Graeme Geldenhuys:

> Hi,
>
> In TPersistent, we have two virtual methods. Assign() which calls
> AssignTo().
>
> 1) Why are they both virtual? It seems like Assign() is what I call a
> template method, farming its work out to other helper methods - in this
> case, AssignTo(). Normally template methods are not virtual, but their
> helper methods (the ones doing the actual work) are. So again, why is
> Assign() virtual?

They are two different directions. AssignTo assigns *from* your current
instance onto another, while Assign assigns *from* the other instance
into yours.
Sure, by default that should be the same, that's why it's sane to have
Assign simply call the other object's AssignTo with Self as target.
But IMHO it can't hurt to have the ability to override that behavior for
only one direction.

> 2) Now seeing that both are virtual, and that is probably not going to
> change in the RTL, which method is the preferred method to override so
> you have the ability to do MyObject.Assign(MySource)? I've been
> overriding Assign(), but thinking that maybe I should have overridden
> AssignTo() instead.

I think that really depends on what direction you want to usually
handle. As far as I understand the code, the call in TPersistent is only
a fallback, intended like that:
if it is not possible to assign some instance onto another instance
(because no class along the hierarchy down to TPersistent implemented an
override for Assign that handles the specific case) it tries, if the
other side maybe can handle it by calling their AssignTo method.

That way you can allow your class to have some
standard/thirdparty/whatever class assigned, while you certainly can't
modify the standard/thirdparty/whatever class to allow assigning *to*
your class (since it doesn't even know your class).
The same goes for the other way around. If you know a foreign class will
try to assign your class, which it doesn't know anything about, it will
ultimately come back calling your AssignTo method which will allow your
class to handle the assignment onto the foreign class.

Best regards,
Andreas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assign() vs AssignTo()

Martin Schreiber-2
In reply to this post by Graeme Geldenhuys-6
On Thursday 11 February 2016 16:13:22 Graeme Geldenhuys wrote:

> Hi,
>
> In TPersistent, we have two virtual methods. Assign() which calls
> AssignTo().
>
> 1) Why are they both virtual? It seems like Assign() is what I call a
> template method, farming its work out to other helper methods - in this
> case, AssignTo(). Normally template methods are not virtual, but their
> helper methods (the ones doing the actual work) are. So again, why is
> Assign() virtual?
>
If one wants to transfer property values from "source" to "dest" one
calls "dest.assign(source)". If "dest" does not know how to handle "source"
it calls "source.assignto(self)".

> 2) Now seeing that both are virtual, and that is probably not going to
> change in the RTL, which method is the preferred method to override so
> you have the ability to do MyObject.Assign(MySource)? I've been
> overriding Assign(), but thinking that maybe I should have overridden
> AssignTo() instead.
>
It depends on what knows to handle what. Sometimes both have to be overridden.

Martin
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assign() vs AssignTo()

Graeme Geldenhuys-6
On 2016-02-11 15:55, Martin Schreiber wrote:
> It depends on what knows to handle what. Sometimes both have to be overridden.

Thanks Martin and Andreas. So it's more about which direction you want
to go.

Now the other thing that surprised be, I thought TPersistent.Assign()
automatically handles protected properties (via RTTI) - thinking that
descendants automatically get such functionality for free. But reviewing
the RTL code, I see Assign() and AssignTo() really has no functionality
implemented by default.

I can only assume that the reason I thought published properties are
handled for you (in the RTL), was because 99.9% of my projects are tiOPF
based, and it always just worked. Looking now at this in more detail, I
see it was indeed tiOPF that always gave me that functionality. Wow, 17+
years later and I only realise that now. :) Never too old to learn. ;-)

Regards,
  - Graeme -


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assign() vs AssignTo()

Martin Schreiber-2
On Thursday 11 February 2016 17:17:32 Graeme Geldenhuys wrote:
>
> Now the other thing that surprised be, I thought TPersistent.Assign()
> automatically handles protected properties (via RTTI) - thinking that
> descendants automatically get such functionality for free. But reviewing
> the RTL code, I see Assign() and AssignTo() really has no functionality
> implemented by default.
>
Correct, it depends much on the actual classes what should happen by
calling "assign()". So "tpersistent" does nothing by default.

Martin
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assign() vs AssignTo()

Dennis


Martin Schreiber wrote:

> On Thursday 11 February 2016 17:17:32 Graeme Geldenhuys wrote:
>> Now the other thing that surprised be, I thought TPersistent.Assign()
>> automatically handles protected properties (via RTTI) - thinking that
>> descendants automatically get such functionality for free. But reviewing
>> the RTL code, I see Assign() and AssignTo() really has no functionality
>> implemented by default.
>>
> Correct, it depends much on the actual classes what should happen by
> calling "assign()". So "tpersistent" does nothing by default.
>
> Martin
>
Is there any sample codes to copy published properties (via RTTI) ?
e.g. psuedo code below

   for i := 0 to properties.count -1 do begin
      case properties[i].type of
         vtInteger :  properties[i].AsInteger :=
Source.PropertiesByName(Properties[i].Name).AsInteger;
        vtdouble : ....
        vtString : ...
      end;
   end;

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assign() vs AssignTo()

Martin Schreiber-2
On Friday 12 February 2016 03:17:57 Dennis wrote:

>
> Is there any sample codes to copy published properties (via RTTI) ?
> e.g. psuedo code below
>
>    for i := 0 to properties.count -1 do begin
>       case properties[i].type of
>          vtInteger :  properties[i].AsInteger :=
> Source.PropertiesByName(Properties[i].Name).AsInteger;
>         vtdouble : ....
>         vtString : ...
>       end;
>    end;
>
MSEgui has such code for "trttistat" component, please see
https://gitlab.com/mseide-msegui/mseide-msegui/raw/master/lib/common/kernel/mserttistat.pas
although it is specialised for saving and editing options.

Martin
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assign() vs AssignTo()

Dennis Poon


Martin Schreiber wrote:

> On Friday 12 February 2016 03:17:57 Dennis wrote:
>> Is there any sample codes to copy published properties (via RTTI) ?
>> e.g. psuedo code below
>>
>>     for i := 0 to properties.count -1 do begin
>>        case properties[i].type of
>>           vtInteger :  properties[i].AsInteger :=
>> Source.PropertiesByName(Properties[i].Name).AsInteger;
>>          vtdouble : ....
>>          vtString : ...
>>        end;
>>     end;
>>
> MSEgui has such code for "trttistat" component, please see
> https://gitlab.com/mseide-msegui/mseide-msegui/raw/master/lib/common/kernel/mserttistat.pas
> although it is specialised for saving and editing options.
>
> Martin
> _______________________________________________
>
Thank you.

Dennis
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assign() vs AssignTo()

Graeme Geldenhuys-6
In reply to this post by Dennis
On 2016-02-12 02:17, Dennis wrote:
> Is there any sample codes to copy published properties (via RTTI) ?
> e.g. psuedo code below

Take a look at tiOPF's TtiObject.AssignPublishedProps() method.

https://sourceforge.net/p/tiopf/code/ci/tiopf2/tree/Core/tiObject.pas#l1156


The tiRTTI.pas unit also has very useful RTTI features - one being
access to properties via "property paths". It walks a object hierarchy
to get or set a property, and does error checking along the way. eg:
  tiSetProperty(lPerson, 'Address.City.Name', 'London');


Regards,
  - Graeme -

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assign() vs AssignTo()

stdreamer
In reply to this post by Graeme Geldenhuys-6
On 11/02/2016 17:13 μμ, Graeme Geldenhuys wrote:

> Hi,
>
> In TPersistent, we have two virtual methods. Assign() which calls
> AssignTo().
>
> 1) Why are they both virtual? It seems like Assign() is what I call a
> template method, farming its work out to other helper methods - in this
> case, AssignTo(). Normally template methods are not virtual, but their
> helper methods (the ones doing the actual work) are. So again, why is
> Assign() virtual?

Different functionality you need both of them for different reasons see
below.

> 2) Now seeing that both are virtual, and that is probably not going to
> change in the RTL, which method is the preferred method to override so
> you have the ability to do MyObject.Assign(MySource)? I've been
> overriding Assign(), but thinking that maybe I should have overridden
> AssignTo() instead.


As a rule of thumb you always override Assign to make sure that your
control can copy data from any other. You only override AssignTo to
enable 3rd party controls to copy data from your controls.

Lets assume that you right a control TDBGrid based on VirtualstringTree ee
TMyDbGrid = class(TVirtualStringTree)
.
.
.
end;
By overriding the assign method you teach TMyDBGrid how to copy data
from a TDBGrid. Now lets assume that you want to be able to copy data
from your TMyDBGrid to TDBGrid as well you have two choices
1) create a new control
   TNewDBGrid = class(TDBGrid)
   end;
  and override the assign method
2) override the AssignTo method of TMyDBgrid control and there copy the
data to TDBGrid your self with out touching TDBgrid.

This is a simple but powerful feature that allows you to teach other
controls how to copy data from your controls with out the need to change
their code. Something common on well written libraries.

PS. The choice of the example control is not random, I came to
understand the importance of AssignTo when I coded my own dbgrid and
wanted to be able to assign data to multiple other grids including the
DevExpress grids.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal