3.0

3.0 | 1 rating Rate this file 21 Downloads (last 30 days) File Size: 4.95 KB File ID: #22965
image thumbnail

Clone Handle Object - using MATLAB OOP

by

 

12 Feb 2009 (Updated )

How to clone an object (deep copy) which inherits reference behaviour from the 'handle' class.

| Watch this File

File Information
Description

The motivation for this demo is that if you have an instance (say 'a') of a custom class that subclasses 'handle', then the command 'b = a;' will produce another reference 'b' to the same object as initially referenced by 'a', effectively creating a 'shallow' copy of the object.

The link to this demo contains a test class which contains the code necessary to produce a clone or 'deep' copy of its instance by way of a method and alternatively, through its constructor.

A test script is provided to demonstrate the cloning of instances of the test class.

Written by Sam Oliver & Bobby Nedelkovski
The MathWorks Australia Pty Ltd
Copyright 2009, The MathWorks, Inc.

Acknowledgements

This file inspired Copy / Clone Method For Handle And Hgsetget Class.

MATLAB release MATLAB 7.9 (R2009b)
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (11)
17 Nov 2011 Shaw

for a handle class contains another handle object. I would do deep copy "recursively". (the following one might face the loop situation.)

classdef B < handle
properties
a % A obj
end
methods
function this = B()
this.a = A();
end

% class A should have the SIMILAR
% clonePublic function
function newObj = clonePublic(this)
props = properties(this);
newObj = B();
for i = 1: length(props)
tmp = this.(props{i});
if(isa(tmp,'handle'))
newObj.(props{i}) = tmp.clonePublic();
else
newObj.(props{i}) = tmp ;
end
end
end
end
end

17 Nov 2011 Shaw

test

07 Sep 2011 Jason

As of R2011A Matlab provides some sort of means for cloning/copying handle objects. Inherit from the matlab.mixin.Copyable class.

It does seem to have a lot of restrictions, but has been good enough for my needs at the moment.

06 Oct 2010 Markus Leuthold

classdef A < handle
properties
b = containers.Map
end
end

please note that containers.Map is itself a handle class, which is not covered in the copyobj function from Volkmar Glauche. You could recursively call copyobj for handle properties, but then you're facing the next problem of private properties (Maps has private props), which cannot be copied as already mentioned.

In order to copy this class, the "ugly" solution from Barry Ridge is unfortunately the only thing which works in order to deep copy an instance of class A.

any news on this issue from Mathworks?

best regards
kusi

07 Jun 2010 Bobby Nedelkovski

Thank you for your suggestions Barry and Holger. I recall encountering Holger's File Exchange posting some time ago and I was going to suggest this in response to Barry's feedback - this is a good workaround given the trade-offs.

06 Jun 2010 Holger Hiebel

I came up with the same "hack" as Barry - this now was already a few years ago... From a programming point of view this is very unaesthetic but it does what it is supposed to do.
I posted it on file exchange as contribution 20972 "copymyobj".
Using this hack is more powerful than any other implementation of a generic copy because it deep-copies also dynamically added properties etc. This is due to reasons which are described by Bobby some 2 postings above.

More than once I complained at The Mathworks that there is no generic function for doing deep copies of classes inheriting from handles - obviously now there is a chance that they are investigating this issue :-)

03 Jun 2010 Barry Ridge

I came up with a bit of a hack for doing this. It uses file-handling, and therefore is not so elegant, but it seems to work. Just add this method to whatever class you want to copy:

function new = copy(this)
save('temp.mat', 'this');
Foo = load('temp.mat');
new = Foo.this;
delete('temp.mat');
end

Example usage (assumes copy() is a method in class MyClass):
A = MyClass();
B = A.copy();

04 Aug 2009 Bobby Nedelkovski

This File Exchange item is now under review. WARNING: Neither the original method (leveraging ‘TestClass.m’ with the ‘copyobj’ method as a template for your custom class) nor using Volkmar’s suggestion (inherit the Volkmar’s proposed ‘copyobj’ method by subclassing ‘TestClass.m’) produces a truly ‘deep’ copy of a handle object. Instead, both methods yield ‘deep’ copies of public properties in the custom superclass hierarchy yet they produce ‘shallow’ copies of private and protected properties. This has to do with the depth in scope of private and protected properties to an instance…

Case: Values of private properties declared in any superclass or protected properties declared in any grandparent class or higher cannot be copied. Accessor methods for private and protected properties can be customised – for instance, getMyProperty(obj). If a private property is modified with a custom set method and since this custom method is not part of the property’s meta-data (i.e. “GetMethod = []” in its corresponding “meta.property” object), one cannot copy the value of the private property using simple assignment with Dynamic Expressions. Moreover, you cannot temporarily modify the property’s “GetMethod=getMyProperty(obj)” nor “GetAccess=Public” meta-data fields to assume necessary control to copy private properties.

I am currently investigating possibilities in producing a truly ‘deep’ copy of a handle object. Please feel free to email any suggestions to bobby.nedelkovski@mathworks.com.au.

26 Jun 2009 Volkmar Glauche  
25 Jun 2009 Volkmar Glauche

This is the code I used for copyobj:
function new = copyobj(obj)
% This method acts as a copy constructor for all derived
% classes.
new = feval(class(obj)); % create new object of correct subclass.
mobj = metaclass(obj);
% Only copy properties which are
% * not dependent or dependent and have a SetMethod
% * not constant
% * not abstract
% * defined in this class or have public SetAccess - not
% sure whether this restriction is necessary
sel = find(cellfun(@(cProp)(~cProp.Constant && ...
~cProp.Abstract && ...
(~cProp.Dependent || ...
(cProp.Dependent && ...
~isempty(cProp.SetMethod))),mobj.Properties));
for k = sel(:)'
new.(mobj.Properties{k}.Name) = obj.(mobj.Properties{k}.Name);
end
end

25 Jun 2009 Volkmar Glauche

I also faced this problem, but for more complicated objects (using e.g. protected and dependent properties). It turned out that just looping over all properties did not do the trick. I had to check all kind of meta-properties to make sure the copyobj method didn't crash.

Updates
07 May 2009

This demo has been updated to use Dynamic Expressions when copying properties of an object.

28 Sep 2009

Added copyright protection to Description field and associated files . Verified this item works with MATLAB R2009b.

Contact us