Class Support for Array-Creation Functions
Extend Array-Creation Functions for Your Class
There are several MATLAB® functions that create arrays of a specific size and type, such as
ones
and zeros
. You can overload many of these functions to work specifically
with your classes. That process is described in this topic. For options for creating
object arrays without overloading existing functions, see Create and Initialize Object Arrays.
Note
createArray
(since R2024a) supports
array creation for many classes without the need for overloading. For more
information, see createArray
. For information about cases when overloading
createArray
might be useful, see createArray Methods to Implement.
Class support for any of the array-creation functions enables you to develop code
that you can share with built-in and user-defined data types. For example, the class
of the variable x
in the following code can be a built-in type
during initial development, and then be replaced by a user-defined class that
transparently overloads zeros
:
cls = class(x); zArray = zeros(m,n,cls);
Array-creation functions create arrays of a specific type in two ways:
Class name syntax — Specify class name that determines the type of array elements.
Prototype object syntax — Provide a prototype object that the function uses to determine the type and other characteristics of the array elements.
For example:
zArray = zeros(2,3,'uint8');
p = uint8([1 3 5; 2 4 6]);
zArray = zeros(2,3,'like',p);
After adding support for these functions to a class named
MyClass
, you can use a similar syntax with that class:
zArray = zeros(2,3,'MyClass');
Or pass an object of your class:
p = MyClass(...); zArray = zeros(size(p),'like',p);
MATLAB uses these arguments to dispatch to the appropriate method in your class.
Array-Creation Functions That Support Overloading
These functions support this kind of overloading:
Scalar Functions That Support Overloading
These functions also support similar overloading, with the exception that the output is always a scalar (or a 1-by-1 sparse matrix):
For these functions, you do not need to specify the size when creating scalars of a specific type. For example:
d = eps('single');
p = single([1 3 5; 2 4 6]);
d = eps('like',p);
After adding support for these functions to a user-defined class, you can use similar syntax with that class as well.
Which Syntax to Use
Classes can support both the class name and the prototype object syntax. To create an array of default objects, use the class name syntax. To create an array of objects with the same type, complexity, and other properties as an existing object, use the prototype syntax.
Implement Support for Array-Creation Functions
Use two separate methods to support an array-creation function. One method implements the class name syntax and the other implements the prototype object syntax.
For example, to support the zeros
function:
Implement the class name syntax:
zeros(...,'ClassName')
As a
Static
method:methods (Static) function z = zeros(varargin) ... end end
Implement the prototype object syntax:
zeros(...,'like',obj)
As a
Hidden
method with thechar
vector'Like'
appended to the name.methods (Hidden) function z = zerosLike(obj,varargin) ... end end
How MATLAB Interprets the Function Call
The special support for array-creation functions results from the interpretation of the syntax.
A call to the
zeros
function of this form:zeros(...,'ClassName')
Calls the class static method with this syntax:
ClassName.zeros(varargin{1:end-1})
A call to the
zeros
function of this form:zeros(...,'like',obj)
Calls the class method with this syntax:
zerosLike(obj,varargin{1:end-2})
Class Name Method Called If Prototype Method Does Not Exist
If your class implements a class name syntax, but does not implement a
prototype object syntax for a particular function, you can still call both
syntaxes. For example, if you implement a static zeros
method
only, you can call:
zeros(...,'like',MyClass(...))
In the case in which you call the prototype object syntax, MATLAB first searches for a method named zerosLike
. If
MATLAB cannot find this method, it calls for the zeros
static method.
This feature is useful if you only need the class name to create the array. You do not need to implement both methods to support the complete array-creation function syntax. When you implement only the class name syntax, a call to a prototype object syntax is the same as the call to the class name syntax.
Support All Function Inputs
The input arguments to an array-creation function can include the dimensions of the array the function returns and possibly other arguments. In general, there are three cases that your methods must support:
No dimension input arguments resulting in the return of a scalar. For example:
z = zeros('MyClass');
One or more dimensions equal to or less than zero, resulting in an empty array. For example:
z = zeros(2,0,'MyClass');
Any number of valid array dimensions specifying the size of the array. For example:
z = zeros(2,3,5,'MyClass');
When the array-creation function calls your class method, it passes the input
arguments, excluding the class name or the literal 'like'
and
the object variable to your method. You can implement your methods with these
signatures:
zeros(varargin)
for “class name” methodszeros(obj,varargin)
for “like prototype object” methods
Sample Class
The Color
class represents a color in a specific color
space, such as, RGB
, HSV
, and so on. The
discussions in Class Name Method Implementations and Prototype Object Method Implementation use this class as a basis for
the overloaded method implementations.
classdef Color properties ColorValues = [0,0,0] ColorSpace = 'RGB' end methods function obj = Color(cSpace,values) if nargin > 0 obj.ColorSpace = cSpace; obj.ColorValues = values; end end end end
Class Name Method Implementations
The zeros
function strips the final
ClassName
char
vector and uses it to form the call to the static method
in the Color
class. The arguments passed to the static method
are the array dimension arguments.
Here is an implementation of a zeros
method for the
Color
class. This implementation:
Defines the
zeros
method asStatic
(required)Returns a scalar
Color
object if the call tozeros
has no dimension argumentsReturns an empty array if the call to
zeros
has any dimensions arguments equal to 0.Returns an array of default
Color
objects. Userepmat
to create an array of the dimensions specified by the call tozeros
.
classdef Color ... methods (Static) function z = zeros(varargin) if (nargin == 0) % For zeros('Color') z = Color; elseif any([varargin{:}] <= 0) % For zeros with any dimension <= 0 z = Color.empty(varargin{:}); else % For zeros(m,n,...,'Color') % Use property default values z = repmat(Color,varargin{:}); end end end end
The zeros
method uses default values for the
ColorValues
property because these values are appropriate
for this application. An implementation of a ones
method
can set the ColorValues
property to
[1,1,1]
, for example.
Suppose that you want to overload the randi
function to achieve the
following objectives:
Define each
ColorValue
property as a 1-by-3 array in the range of 1 to a specified maximum value (for example, 1–255).Accommodate scalar, empty, and multidimensional array sizes.
Return an array of
Color
objects of the specified dimensions, each with randomColorValues
.
classdef Color ... methods (Static) function r = randi(varargin) if (nargin == 0) % For randi('ClassName') r = Color('RGB',randi(255,[1,3])); elseif any([varargin{2:end}] <= 0) % For randi with any dimension <= 0 r = Color.empty(varargin{2:end}); else % For randi(max,m,n,...,'ClassName') if numel([varargin{:}]) < 2 error('Not enough input arguments') end dims = [varargin{2:end}]; r = zeros(dims,'Color'); for k = 1:prod(dims) r(k) = Color('RGB',randi(varargin{1},[1,3])); end end end end end
Prototype Object Method Implementation
The objective of a method that returns an array of objects that are
“like a prototype object” depends on the requirements of the
class. For the Color
class, the zerosLike
method creates objects that have the ColorSpace
property
value of the prototype object, but the ColorValues
are all
zero.
Here is an implementation of a zerosLike
method for the
Color
class. This implementation:
Defines the
zerosLike
method asHidden
Returns a scalar
Color
object if the call to thezeros
function has no dimension argumentsReturns an empty array if the call to the
zeros
function has any dimension arguments that are negative or equal to 0.Returns an array of
Color
objects of the dimensions specified by the call to thezeros
function.
classdef Color ... methods (Hidden) function z = zerosLike(obj,varargin) if nargin == 1 % For zeros('like',obj) cSpace = obj.ColorSpace; z = Color; z.ColorSpace = cSpace; elseif any([varargin{:}] <= 0) % For zeros with any dimension <= 0 z = Color.empty(varargin{:}); else % For zeros(m,n,...,'like',obj) if ~isscalar(obj) error('Prototype object must be scalar') end obj = Color(obj.ColorSpace,zeros(1,3,'like',obj.ColorValues)); z = repmat(obj,varargin{:}); end end end end
Full Class Listing
Here is the Color
class definition with the overloaded
methods.
Note
In actual practice, the Color
class requires error
checking, color space conversions, and so on. This overly simplified version
illustrates the implementation of the overloaded methods.
classdef Color properties ColorValues = [0,0,0] ColorSpace = 'RGB' end methods function obj = Color(cSpace,values) if nargin > 0 obj.ColorSpace = cSpace; obj.ColorValues = values; end end end methods (Static) function z = zeros(varargin) if (nargin == 0) % For zeros('ClassName') z = Color; elseif any([varargin{:}] <= 0) % For zeros with any dimension <= 0 z = Color.empty(varargin{:}); else % For zeros(m,n,...,'ClassName') % Use property default values z = repmat(Color,varargin{:}); end end function r = randi(varargin) if (nargin == 0) % For randi('ClassName') r = Color('RGB',randi(255,[1,3])); elseif any([varargin{2:end}] <= 0) % For randi with any dimension <= 0 r = Color.empty(varargin{2:end}); else % For randi(max,m,n,...,'ClassName') if numel([varargin{:}]) < 2 error('Not enough input arguments') end dims = [varargin{2:end}]; r = zeros(dims,'Color'); for k = 1:prod(dims) r(k) = Color('RGB',randi(varargin{1},[1,3])); end end end end methods (Hidden) function z = zerosLike(obj,varargin) if nargin == 1 % For zeros('like',obj) cSpace = obj.ColorSpace; z = Color; z.ColorSpace = cSpace; elseif any([varargin{:}] <= 0) % For zeros with any dimension <= 0 z = Color.empty(varargin{:}); else % For zeros(m,n,...,'like',obj) if ~isscalar(obj) error('Prototype object must be scalar') end obj = Color(obj.ColorSpace,zeros(1,3,'like',obj.ColorValues)); z = repmat(obj,varargin{:}); end end end end
Overloading createArray
createArray
(since R2024a) supports most classes without the need
for overloading. However, if your class meets one or more of these conditions,
implement the static createArray
method:
Your class does not have a default constructor.
Your class has a default constructor that returns an empty array.
Your class has properties that need to be dynamically initialized for each instance in the array.
Implement the createArrayLike
method if your
class does not support creating an array from an existing object through indexed
assignment. However, most classes do not need to overload
createArrayLike
because
createArray
usually supports the preservation of
property values.
The process of overloading the createArray
function is
similar to zeros
, but the syntaxes are slightly different
because of the FillValue
name-value arguments for
createArray
.
createArray
Methods to Implement
Method | Function Signature | When the Method Is Called |
---|---|---|
static |
|
|
|
|
|