Main Content

Implement Copy for Handle Classes

Copy Method for Handle Classes

Copying a handle variable results in another handle variable that refers to the same object. You can add copy functionality to your handle class by subclassing matlab.mixin.Copyable. The inherited copy method enables you to make shallow copies of objects of the class. The CopyObj class shows the behavior of copy operations.

classdef CopyObj < matlab.mixin.Copyable
   properties
      Prop
   end
end

Create an object of the CopyObj class and assign the handle of a line object to the property Prop.

a = CopyObj;
a.Prop = line;

Copy the object.

b = copy(a);

Confirm that the handle variables a and b refer to different objects.

a == b
ans =

  logical

   0

However, the line object referred to by a.Prop has not been copied. The handle in a.Prop refers to the same object as the handle in b.Prop.

a.Prop == b.Prop
ans =

  logical

   1

For more detailed information on the behavior of the copy operation, see copy.

Customize Copy Operation

Customize handle object copy behavior by deriving your class from matlab.mixin.Copyable. The matlab.mixin.Copyable class is an abstract base class that derives from the handle class. matlab.mixin.Copyable provides a template for customizing object copy operations by defining:

  • copy — Sealed method that defines the interface for copying objects

  • copyElement — Protected method that subclasses can override to customize object copy operations for the subclass

The matlab.mixin.Copyable copy method, calls the copyElement method. Your subclass customizes the copy operation by defining its own version of copyElement.

The default implementation of copyElement makes shallow copies of all the nondependent properties. copyElement copies each property value and assigns it to the new (copied) property. If a property value is a handle object, copyElement copies the handle, but not the underlying data.

To implement different copy behavior for different properties, override copyElement. For example, the copyElement method of the SpecializedCopy class:

  • Creates a new class object

  • Copies the value of Prop1 to the new object

  • Reinitializes the default value of Prop2 by adding a timestamp when the copy is made

classdef SpecializedCopy < matlab.mixin.Copyable
   properties
      Prop1
      Prop2 = datestr(now)
   end
   methods(Access = protected)
      function cp = copyElement(obj)
         cp = SpecializedCopy;
         cp.Prop1 = obj.Prop1;
         cp.Prop2 = datestr(now);
      end
   end
end

Create an object of the class and assign a value to Prop1:

a  = SpecializedCopy;
a.Prop1 = 7
a = 

  SpecializedCopy with properties:

    Prop1: 7
    Prop2: '17-Feb-2015 17:51:23'

Use the inherited copy method to create a copy of a:

b = copy(a)
b = 

  SpecializedCopy with properties:

    Prop1: 7
    Prop2: '17-Feb-2015 17:51:58'

The copy (object b) has the same value for Prop1, but the subclass copyElement method assigned a new value to Prop2. Notice the different timestamp.

Copy Properties That Contain Handles

Copying an object also copies the values of object properties. Object properties can contain other objects, including handle objects. If you simply copy the value of a property that contains a handle object, you are actually copying the handle, not the object itself. Therefore, your copy references the same object as the original object. Classes that derive from the matlab.mixin.Copyable class can customize the way the copy method copies objects of the class.

Class to Support Handle Copying

Suppose that you define a class that stores a handle in an object property. You want to be able to copy objects of the class and want each copy of an object to refer to a new handle object. Customize the class copy behavior using these steps:

  • Create a subclass of matlab.mixin.Copyable.

  • Override copyElement to control how the property containing the handle is copied.

  • Because the property value is a handle, create a new default object of the same class.

  • Copy property values from the original handle object to the new handle object.

The HandleCopy class customizes copy operations for the property that contains a handle object. The ColorProp class defines the handle object to assign to Prop2:

Create an object and assign property values:

a = HandleCopy;
a.Prop1 = 7;
a.Prop2 = ColorProp;

Make a copy of the object using the copy method inherited from matlab.mixin.Copyable:

b = copy(a);

Demonstrate that the handle objects contained by objects a and b are independent. Changing the value on object a does not affect object b:

a.Prop2.Color = 'red';
b.Prop2.Color
ans =

blue

HandleCopy

The HandleCopy class customizes the copy operation for objects of this class.

classdef HandleCopy < matlab.mixin.Copyable
   properties
      Prop1 % Shallow copy
      Prop2 % Handle copy
   end
   methods (Access = protected)
      function cp = copyElement(obj)
         % Shallow copy object
         cp = copyElement@matlab.mixin.Copyable(obj);
         % Get handle from Prop2
         hobj = obj.Prop2;
         % Create default object
         new_hobj = eval(class(hobj));
         % Add public property values from orig object
         HandleCopy.propValues(new_hobj,hobj);
         % Assign the new object to property
         cp.Prop2  = new_hobj;
      end
   end
   methods (Static)
      function propValues(newObj,orgObj)
         pl = properties(orgObj);
         for k = 1:length(pl)
            if isprop(newObj,pl{k})
               newObj.(pl{k}) = orgObj.(pl{k});
            end
         end
      end
   end
end

ColorProp

The ColorProp class defines a color by assigning an RGB value to its Color property.

classdef ColorProp < handle
   properties
      Color = 'blue';
   end
end

Exclude Properties from Copy

Use the NonCopyable property attribute to indicate that you do not want a copy operation to copy a particular property value. By default, NonCopyable is false, indicating that the property value is copyable. You can set NonCopyable to true only on properties of handle classes.

For classes that derive from matlab.mixin.Copyable, the default implementation of copyElement honors the NonCopyable attribute. Therefore, if a property has its NonCopyable attribute set to true, then copyElement does not copy the value of that property. If you override copyElement in your subclass, you can choose how to use the NonCopyable attribute.

Set the Attribute to Not Copy

Set NonCopyable to true in a property block:

properties (NonCopyable)
   Prop1
end

Default Values

If a property that is not copyable has a default value assigned in the class definition, the copy operation assigns the default value to the property. For example, the CopiedClass assigns a default value to Prop2.

classdef CopiedClass < matlab.mixin.Copyable
   properties (NonCopyable)
      Prop1
      Prop2 = datestr(now) % Assign current time
   end
end

Create an object to copy and assign a value to Prop1:

a = CopiedClass;
a.Prop1 = 7
a = 

  CopiedClass with properties:

    Prop1: 7
    Prop2: '17-Feb-2015 15:19:34'

Copy a to b using the copy method inherited from matlab.mixin.Copyable:

b = copy(a)
b = 

  CopiedClass with properties:

    Prop1: []
    Prop2: '17-Feb-2015 15:19:34'

In the copy b, the value of Prop1 is not copied. The value of Prop2 is set to its default value, which MATLAB® determined when first loading the class. The timestamp does not change.

Objects with Dynamic Properties

Subclasses of the dynamicprops class allow you to add properties to an object of the class. When a class derived from dynamicprops is also a subclass of matlab.mixin.Copyable, the default implementation of copyElement does not copy dynamic properties. The default value of NonCopyable is true for dynamic properties.

The default implementation of copyElement honors the value of a dynamic property NonCopyable attribute. If you want to allow copying of a dynamic property, set its NonCopyable attribute to false. Copying a dynamic property copies the property value and the values of the property attributes.

For example, this copy operation copies the dynamic property, DynoProp, because its NonCopyable attribute is set to false. The object obj must be an instance of a class that derives from both dynamicprops and matlab.mixin.Copyable:

obj = MyDynamicClass;
p = addprop(obj,'DynoProp');
p.NonCopyable = false;
obj2 = copy(obj);

See Also

Related Topics