How to Define Handle-Compatible Classes
What Is Handle Compatibility?
A class is handle compatible if:
It is a handle class
Its
HandleCompatible
attribute is set totrue
The HandleCompatible
class attribute identifies classes that you can combine with handle classes when specifying a set of superclasses.
Handle compatibility provides greater flexibility when defining abstract superclasses. For example, when using superclasses that support both handle and value subclasses, handle compatibility removes the need to define both a handle version and a nonhandle version of a class.
A Handle Compatible Class
In this example, the Utility
class defines a method to
reset property values to the default values defined in the respective class
definition. This functionality is useful to both handle and value
subclasses.
classdef (HandleCompatible) Utility methods function obj = resetDefaults(obj) mc = metaclass(obj); mp = mc.PropertyList; for k=1:length(mp) if mp(k).HasDefault && ~strcmp(mp(k).SetAccess,'private') obj.(mp(k).Name) = mp(k).DefaultValue; end end end end end
The Utility
class is handle compatible. Therefore, you can use it in the derivation of classes that are either handle classes or value classes. See Class Introspection and Metadata for information on using meta-data classes.
Return Modified Objects
The resetDefaults
method defined by the Utility
class returns the object it modifies. When you call resetDefaults
with a value object, the method must return the modified object. It is important to implement methods that work with both handle and value objects in a handle compatible superclass. See Object Modification for more information on modifying handle and value objects.
Consider the behavior of a value class that subclasses the Utility
class. The PropertyDefaults
class defines three properties, all of which have default values:
classdef PropertyDefaults < Utility properties p1 = datestr(rem(now,1)) % Current time p2 = 'red' % Character vector p3 = pi/2 % Result of division operation end end
Create a PropertyDefaults
object. MATLAB® evaluates the expressions assigned as default property values when the class is first loaded. MATLAB uses these same default values whenever you create an instance of this class in the current MATLAB session.
pd = PropertyDefaults
pd = PropertyDefaults with properties: p1: ' 4:42 PM' p2: 'red' p3: 1.5708
Assign new values that are different from the default values:
pd.p1 = datestr(rem(now,1));
pd.p2 = 'green';
pd.p3 = pi/4;
All pd
object property values now contain values that are different from the default values originally defined by the class:
pd
pd = PropertyDefaults with properties: p1: ' 4:45 PM' p2: 'green' p3: 0.7854
Call the resetDefaults
method, which is inherited from the Utility
class. Because the PropertyDefaults
class is not a handle class, return the modified object.
pd = pd.resetDefaults
pd = PropertyDefaults with properties: p1: ' 4:54 PM' p2: 'red' p3: 1.5708
If the PropertyDefaults
class was a handle class, then you would not need to save the object returned by the resetDefaults
method. To design a handle compatible class like Utility
, ensure that all methods work with both kinds of classes.
Subclassing Handle-Compatible Classes
According to the rules described in Handle Compatibility Rules, when you combine a handle superclass with a handle-compatible superclass, the result is a handle subclass, which is handle compatible.
However, subclassing a handle-compatible class does not necessarily result in the subclass being handle compatible. Consider the following two cases, which demonstrate two possible results.
Combine Nonhandle Utility Class with Handle Classes
Define a class that subclasses a handle class and the handle-compatible
Utility
class discussed in A Handle Compatible Class. The HPropertyDefaults
class has these characteristics:
It is a handle class because it derives from
handle
.All its superclasses are handle compatible because handle classes are handle compatible by definition.
classdef HPropertyDefaults < handle & Utility properties GraphPrim = line Width = 1.5 Color = 'black' end end
The HPropertyDefaults
class is handle compatible.
hpd = HPropertyDefaults; mc = metaclass(hpd); mc.HandleCompatible
ans = 1
Nonhandle Subclasses of a Handle-Compatible Class
If you subclass both a value class that is not handle compatible and a handle compatible class, the subclass is a nonhandle compatible value class. The ValueSub
class:
Is a value class (it does not derive from
handle
.)One of its superclasses is handle compatible (the
Utility
class).
classdef ValueSub < MException & Utility methods function obj = ValueSub(str1,str2) obj = obj@MException(str1,str2); end end end
The ValueSub
class is a nonhandle-compatible value class because the MException
class does not define the HandleCompatible
attribute as true
:
hv = ValueSub('MATLAB:narginchk:notEnoughInputs',... 'Not enough input arguments.'); mc = metaclass(hv); mc.HandleCompatible
ans = 0