Copying objects [message #18093] |
Tue, 30 November 1999 00:00  |
James Tappin
Messages: 54 Registered: December 1995
|
Member |
|
|
Is there a "clean" way to make a copy of an object. The best I could do for a
nice easy case with no pointers or object references in the class was:
pro Object1::set_all, tstr
for i = 0, n_tags(tstr)-1 do self.(i) = tstr.(i)
end
function Object1::copy
temp = {object1}
for i = 0, n_tags(temp)-1 do temp.(i) = self.(i)
newobj = obj_new('object1')
newobj -> set_all, temp
return, newobj
end
While it works, it seems to be a bit of a kludge. Is there a better way?
James
--
+------------------------+-------------------------------+-- -------+
| James Tappin | School of Physics & Astronomy | O__ |
| sjt@star.sr.bham.ac.uk | University of Birmingham | -- \/` |
| Ph: 0121-414-6462. Fax: 0121-414-3722 | |
+--------------------------------------------------------+-- -------+
|
|
|
|
Re: Copying objects [message #18136 is a reply to message #18093] |
Fri, 03 December 1999 00:00   |
J.D. Smith
Messages: 214 Registered: August 1996
|
Senior Member |
|
|
David Fanning wrote:
>
> J.D. Smith (jdsmith@astro.cornell.edu) writes:
>
>> The easiest way to copy objects in bulk, composited objects and all, is to save
>> and restore, using:
>>
>> save,obj,FILENAME=savefile
>> restore,savefile,RESTORED_OBJECTS=newobj,/RELAXED_STRUCTURE_ ASSIGNMENT
>> newobj=newobj[0]
>>
>> Don't forget that the object reference variable is also restored, and will
>> overwrite a variable with the same name in that level (but this can be used to
>> advantage -- see below). Also beware of later restoring objects, since their
>> methods (and those of their superclasses) will be unavailable, and will not be
>> located automatically. You can prevent this... see a posting from last year on
>> restoring objects (I can re-post my resolve_obj if necessary).
>
> The lightly edited conversation JD refers to on the
> newsgroup about restoring objects can be found here:
>
> http://www.dfanning.com/tips/saved_objects.html
>
Actually, David, your website posting is incomplete, because it does not mention
the problem of superclass method resolution. I emailed you about this last
year, but it must have slipped through the cracks. The basic problem is that
superclass methods are not automatically searched and compiled by the above
procedure, since a restored object contains implicitly in its definition the
class definitions of all its superclasses. Basically it's the same problem
cropping up again. The solution is to recursively work your way up the
inheritance tree by hand. *But*, one more wrinkle: if you're often updating
your class definition, you need to have it defined *before* restoring the
object, to avoid having the older definition (as saved with the object) shadow
your new one. A new resolve_obj (see attached), and a method which addresses
all of these concerns is therefore:
resolve_obj,CLASS='class'
restore,file, RESTORED_OBJECTS=obj,/RELAXED_STRUCTURE_ASSIGNMENT
Notice that now we are burdened with knowing *which* class to pre-compile.
However, if you are willing to live with the potential of older class
definitions shadowing newer ones, or don't mind ensuring the most recent class
version is defined before any object restoration occurs (though in practice that
would eliminate the problem), you can still use:
restore,file, RESTORED_OBJECTS=obj,/RELAXED_STRUCTURE_ASSIGNMENT
resolve_obj,obj[0]
without worrying about which class is being restored. The only difference here
is that putting the restore first opens up the potential of class definition
shadowing. Sometimes this isn't a concern, or the convenience and generality of
a generic restoration scheme outweighs the precautions which must be taken when
using it.
The updated routine is attached. Notice the use of routine_info() to avoid
compiling any class already compiled. Also note that the original routine will
work well enough for classes which do not INHERIT... but most of the good one do
;).
JD
--
J.D. Smith |*| WORK: (607) 255-5842
Cornell University Dept. of Astronomy |*| (607) 255-6263
304 Space Sciences Bldg. |*| FAX: (607) 255-5875
Ithaca, NY 14853 |*|
pro resolve_obj,obj,CLASS=class,ROUTINE_INFO=ri
if n_params() ne 0 then begin
if NOT obj_valid(obj) then begin
message,'Object is not valid.'
endif
class=obj_class(obj)
endif
if n_elements(ri) eq 0 then ri=routine_info()
for i=0,n_elements(class)-1 do begin
defpro=class[i]+'__DEFINE'
if (where(ri eq defpro))[0] eq -1 then begin
;; Compile and define the class.
call_procedure,defpro
endif
supers=obj_class(class[i],/SUPERCLASS,COUNT=cnt)
if cnt gt 0 then resolve_obj,CLASS=supers,ROUTINE_INFO=ri
endfor
end
|
|
|
Re: Copying objects [message #18151 is a reply to message #18093] |
Thu, 02 December 1999 00:00   |
davidf
Messages: 2866 Registered: September 1996
|
Senior Member |
|
|
J.D. Smith (jdsmith@astro.cornell.edu) writes:
> The easiest way to copy objects in bulk, composited objects and all, is to save
> and restore, using:
>
> save,obj,FILENAME=savefile
> restore,savefile,RESTORED_OBJECTS=newobj,/RELAXED_STRUCTURE_ ASSIGNMENT
> newobj=newobj[0]
>
> Don't forget that the object reference variable is also restored, and will
> overwrite a variable with the same name in that level (but this can be used to
> advantage -- see below). Also beware of later restoring objects, since their
> methods (and those of their superclasses) will be unavailable, and will not be
> located automatically. You can prevent this... see a posting from last year on
> restoring objects (I can re-post my resolve_obj if necessary).
The lightly edited conversation JD refers to on the
newsgroup about restoring objects can be found here:
http://www.dfanning.com/tips/saved_objects.html
Cheers,
David
--
David Fanning, Ph.D.
Fanning Software Consulting
Phone: 970-221-0438 E-Mail: davidf@dfanning.com
Coyote's Guide to IDL Programming: http://www.dfanning.com/
Toll-Free IDL Book Orders: 1-888-461-0155
|
|
|
Re: Copying objects [message #18154 is a reply to message #18093] |
Thu, 02 December 1999 00:00   |
J.D. Smith
Messages: 214 Registered: August 1996
|
Senior Member |
|
|
James Tappin wrote:
>
> Is there a "clean" way to make a copy of an object. The best I could do for a
> nice easy case with no pointers or object references in the class was:
>
> pro Object1::set_all, tstr
> for i = 0, n_tags(tstr)-1 do self.(i) = tstr.(i)
> end
>
> function Object1::copy
> temp = {object1}
> for i = 0, n_tags(temp)-1 do temp.(i) = self.(i)
> newobj = obj_new('object1')
> newobj -> set_all, temp
> return, newobj
> end
>
> While it works, it seems to be a bit of a kludge. Is there a better way?
>
The easiest way to copy objects in bulk, composited objects and all, is to save
and restore, using:
save,obj,FILENAME=savefile
restore,savefile,RESTORED_OBJECTS=newobj,/RELAXED_STRUCTURE_ ASSIGNMENT
newobj=newobj[0]
Don't forget that the object reference variable is also restored, and will
overwrite a variable with the same name in that level (but this can be used to
advantage -- see below). Also beware of later restoring objects, since their
methods (and those of their superclasses) will be unavailable, and will not be
located automatically. You can prevent this... see a posting from last year on
restoring objects (I can re-post my resolve_obj if necessary).
Other interesting applications of this method:
Objects which replace themselves from file. Don't forget to kill the replaced
object:
oldself=self
; Be sure to do some error-catching in here!
restore,file,/RELAXED_STRUCTURE_ASSIGNMENT ;self is overwritten from file!
;; Do some error catching, but if it worked...
obj_destroy,oldself
and viola! a new self-identity! Instant "Revert from disk" command. I use it
all the time.
Another fun and useful technique: "disconnect" irrelevant portions of objects
before saving them, especially those which will implicitly define structures and
classes that might be changing alot, and which you don't want to keep up with
the method resolution issue. Simply use pointers, and do something like:
uselesssav=self.UselessStructPtr
self.UselessStructPtr=ptr_new() ; save a null pointer instead!
self->Save
self.UselessStructPtr=uselesssav
etc. You get the idea. Be sure to disconnect only those things for which a
null-pointer value isn't disasterous!
Good Luck,
JD
--
J.D. Smith |*| WORK: (607) 255-5842
Cornell University Dept. of Astronomy |*| (607) 255-6263
304 Space Sciences Bldg. |*| FAX: (607) 255-5875
Ithaca, NY 14853 |*|
|
|
|
|
|