Object Arrays, Customization and Introspection

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

Written against MATLAB R2026b. createArray needs R2024a, the matlab.metadata namespace replaced meta in R2024a, and metafunction needs R2026a. The Octave 11.3.0 sessions below cover only what Octave’s partial classdef support accepts: building and indexing object arrays, and the basic query functions. Everything else (createArray, matlab.mixin.*, the matlab.metadata classes, metafunction) is checked line by line against the R2026b documentation and labelled "not run here".

An object array is an ordinary MATLAB array whose elements are objects of one class. Customization means changing how such objects display and how arrays of them may be formed. Introspection (also called reflection) means asking a class, an object or a function what it contains, at run time, from code. The three topics share one idea: in MATLAB a class instance is an array first and a scalar second, so the same rules (size, indexing, concatenation, empty arrays) apply to user-defined classes as to numeric arrays. The class definition itself is on classdef Basics; value versus handle behavior is on Value and Handle Classes. The examples use the heatflow.Plate class of the heatflow scenario (The heatflow scenario).

The example class

The class below is the Plate value class of the shared heatflow API, shortened to what this page needs. It has no property validation, so that the file also loads in Octave; validation is covered on Properties and Methods. Save it as +heatflow/Plate.m in a folder on the path.

classdef Plate
    % Plate  Rectangular plate with a temperature field.
    properties
        Nx = 1        % grid points along x
        Ny = 1        % grid points along y
        Dx = 1        % grid spacing in meters
        Alpha = 1     % thermal diffusivity in m^2/s
        T = 20        % temperature field in degC, Ny-by-Nx
    end
    methods
        function obj = Plate(nx, ny, dx, alpha)
            if nargin > 0
                obj.Nx = nx;
                obj.Ny = ny;
                obj.Dx = dx;
                obj.Alpha = alpha;
                obj.T = 20*ones(ny, nx);
            end
        end

        function m = maxTemperature(obj)
            % One result per element, so it works on any object array.
            m = zeros(size(obj));
            for k = 1:numel(obj)
                m(k) = max(obj(k).T(:));
            end
        end
    end
end

Two details matter for everything below. The constructor works when called with no arguments (nargin > 0 guard), because MATLAB calls it that way to fill gaps in an array. And maxTemperature loops over numel(obj) instead of assuming a scalar, so it accepts an array.

Object arrays

Building an array

MATLAB documents three ways to create an object array, plus building it inside a constructor (all on the documentation page "Create and Initialize Object Arrays").

Technique What happens

A loop, plates(k) = heatflow.Plate(...)

Each assignment calls the constructor with your arguments. Use this when elements need different values.

createArray(dims,"ClassName") (R2024a)

Calls the constructor once with no arguments and fills the array with copies of that instance. For a handle class the elements are distinct handles, although the constructor still ran once.

createArray(dims,Like=prototype)

The result has the class of prototype, but the elements come from one default-constructor call. The property values of the prototype are not preserved.

createArray(dims,FillValue=instance)

Does not call the constructor; the instance is copied into every element. This is the form for filling an array with a configured object.

Assign the last element, a(2,2) = obj

MATLAB calls the no-argument constructor once and fills every other element with copies of that default object; the element you assigned keeps its own values. If the constructor cannot be called with no arguments, this errors.

ClassName.empty or ClassName.empty(0,3)

An empty array of the class. At least one dimension must be 0. Assigning into it grows it.

The heatflow example builds a row of three plates with different grids, reads one property from all of them, and applies the vectorized method:

sizes = [4 3; 8 6; 16 12];
for k = 1:size(sizes,1)
    plates(k) = heatflow.Plate(sizes(k,1), sizes(k,2), 0.01, 1e-4);
end
disp(size(plates))
disp(class(plates))
nx = [plates.Nx]
plates(2).T(3,4) = 95;
tmax = maxTemperature(plates)

spare(3) = heatflow.Plate(2, 2, 0.01, 1e-4);
spareNx = [spare.Nx]

Octave 11.3.0 output (MATLAB prints the same values; the exact spacing of the display can differ):

   1   3
heatflow.Plate
nx =

    4    8   16

tmax =

   20   95   20

spareNx =

   1   1   2

The last two lines show the fill rule: spare(3) was assigned, so spare(1) and spare(2) are default Plate objects with Nx = 1, and only the third has Nx = 2. Growing an array in a loop reallocates it each time, just as with numeric arrays; for a known size, preallocate with createArray (R2024a) or by assigning the last element first.

The createArray and empty forms are not run here, because Octave 11.3.0 has no createArray and rejects heatflow.Plate.empty:

blank = createArray(1,3,"heatflow.Plate");          % three default plates
proto = heatflow.Plate(8,6,0.01,1e-4);
copies = createArray(2,2,FillValue=proto);          % 2-by-2, all equal to proto
none = heatflow.Plate.empty(0,3);                   % 0-by-3, no elements
none(2) = proto;                                    % grows to 1-by-2

The last statement of that listing grows none to hold two elements, with element 1 filled by the no-argument constructor. isempty(none) is true before that assignment and false after it. An empty array still has a class: class(none) is heatflow.Plate.

Reading and writing properties of an array

Dot notation on an array returns a comma-separated list, one value per element (see Comma-Separated Lists). Enclose it in brackets to collect a vector, or in braces for a cell array when the values have different sizes:

nx    = [plates.Nx];                 % numeric row vector
grids = {plates.T};                  % cell array, one temperature matrix each
big   = plates([plates.Nx] > 5);     % logical indexing on a property
second = plates(2).Alpha;            % one element, then one property
sub   = [plates(2:3).Nx];            % a range of elements

The reverse does not work: there is no single assignment that sets one property of every element, so plates.Alpha = 2e-4 errors. Use a loop, or deal the values out with a comma-separated list on the left side, [plates.Alpha] = deal(2e-4) (the deal form comes from the general list rules and is not run here; Octave 11.3.0 does not accept it on object arrays). Element-wise assignment, plates(2).Alpha = 3e-4, and deletion, plates(2) = [], work as for any array. The documentation adds one restriction: dynamic properties belong to individual objects, so MATLAB refuses to read them from a whole array in one statement; index each object.

Two concatenation checks run on the same Octave session as above, with plates after the loop:

big = plates([plates.Nx] > 5);
disp(numel(big))
plates(2) = [];
disp(size(plates))
col = [plates(1); plates(2)];
disp(size(col))

which printed 2, then 1 2, then 2 1 (Octave 11.3.0). Deleting an element shortens the array, and vertical concatenation stacks objects into a column.

Methods on arrays

When you pass an object array to a method, MATLAB calls the method once with the whole array. The method must therefore be written to handle arrays: collect properties with [obj.Prop] or loop over numel(obj), as maxTemperature does. A method that only works on scalar input errors when given a nonscalar array. You can also call a method on one element with ordinary function syntax, maxTemperature(plates(3)).

For a function applied to every element, a loop over numel works in every release. On MATLAB, arrayfun(@(p) p.Nx*p.Ny, plates) is the compact form (not run here: Octave 11.3.0 fails with "can’t perform indexing operation on array of heatflow.Plate objects"). Write the loop when the code must run in both.

Concatenation, class conversion and heterogeneous arrays

[a,b] joins objects into an array of one class. The documentation states these rules for objects of different classes:

  • MATLAB tries to convert every object to the dominant class. User-defined classes take precedence over built-in classes such as double; if neither dominates, the leftmost object does.

  • To convert an object of the other class, MATLAB looks for a conversion method with the dominant class name in the non-dominant class, and otherwise passes the object to the dominant class constructor. A failed conversion is an error.

  • MATLAB does not convert to a common superclass. That requires a heterogeneous hierarchy.

  • A class can redefine horzcat, vertcat or cat to change the process.

Octave 11.3.0 shows the error case: [plates, 5] stops with cat: cannot convert from type "double" to type "heatflow.Plate" because Plate has no conversion from a double. MATLAB’s wording differs and is not run here.

A heterogeneous array mixes objects of different classes that share a root class derived directly from matlab.mixin.Heterogeneous. The class of the array is the most specific superclass common to its elements. An illustrative hierarchy for the heatflow plate edges (not run here):

classdef EdgeCondition < matlab.mixin.Heterogeneous
    % Root of the hierarchy; its subclasses can share one array.
    methods (Abstract)
        value = applyTo(obj, T)
    end
end

Subclasses such as a fixed-temperature edge and an insulated edge each derive from EdgeCondition. [fixedEdge insulatedEdge] then has class EdgeCondition, and applyTo(edges, T) dispatches on each element’s own class. The root class may need to override the protected static method getDefaultScalarElement so that MATLAB can fill gaps in the array. matlab.mixin.Heterogeneous is abstract and handle-compatible, and its cat, horzcat and vertcat methods are public.

Identifying the class of an array

class(a) returns the name of the most derived class as a character vector, including the namespace (heatflow.Plate). isa(a,"heatflow.Plate") is also true for subclasses and for a category such as "numeric", "float" or "integer" when the object derives from a built-in numeric class. Use strcmp(class(a),"int16") when you must exclude subclasses. The isa and class calls above ran in Octave 11.3.0 on the Plate object.

Customizing display

MATLAB shows an object that is not terminated by a semicolon with a header (the class name and, for arrays, the size), a list of the public non-hidden properties in definition order, and a footer. The default disp and display methods are added to every class that does not define its own. A class can change this in two ways.

matlab.mixin.CustomDisplay

Derive from matlab.mixin.CustomDisplay (R2013b). The class is abstract and handle-compatible, so it combines with value and handle superclasses. It defines disp, display and details as public, sealed and hidden methods: you do not override those, you override protected customization methods instead.

Group Methods to override (all Access = protected)

Part builders

getHeader, getPropertyGroups, getFooter; also getClassNameForHeader, getSimpleHeader, getDetailedHeader, getDetailedFooter.

State handlers, one per object state

displayScalarObject (a valid scalar), displayNonScalarObject (more than one element), displayEmptyObject (zero elements), displayScalarHandleToDeletedObject.

Utilities

displayPropertyGroups, convertDimensionsToString, getHandleText, getDeletedHandleText.

The default getHeader builds the class name followed by with properties:; the simple footer is empty. Since R2026a, getHeader and getFooter may return strings as well as character vectors. details output is not changed by the interface. The documentation also says the class cannot be used to customize display of enumeration classes.

getPropertyGroups returns a row of matlab.mixin.util.PropertyGroup objects. The constructor is P = matlab.mixin.util.PropertyGroup(propertyList,title), where the list is a cell array of names, a string array or a struct whose fields are the names. In a struct the values are what MATLAB prints, so a struct lets you display a computed number next to stored properties; the documentation says to use a struct only for a scalar object and a list of names otherwise.

Illustrative heatflow version (not run here; the output shape follows the documentation example for a two-group class, but no output is shown because it was not run):

classdef Plate < matlab.mixin.CustomDisplay
    properties
        Nx = 1
        Ny = 1
        Dx = 1
        Alpha = 1
        T = 20
    end
    methods (Access = protected)
        function groups = getPropertyGroups(obj)
            if ~isscalar(obj)
                groups = getPropertyGroups@matlab.mixin.CustomDisplay(obj);
            else
                gridGroup = matlab.mixin.util.PropertyGroup(["Nx" "Ny" "Dx"],"Grid");
                summary = struct("Alpha",obj.Alpha, ...
                                 "MaxTemperature",max(obj.T(:)));
                phys = matlab.mixin.util.PropertyGroup(summary,"Physics");
                groups = [gridGroup phys];
            end
        end
        function s = getFooter(~)
            s = "Temperatures in degC";
        end
    end
end

The nonscalar branch delegates to the superclass implementation, which is the documented pattern for keeping the default array display. The matrix T is left out of the display because a 1000-by-1000 field would flood the Command Window.

Octave 11.3.0 has no matlab.mixin namespace. Declaring classdef CD < matlab.mixin.CustomDisplay and calling CD() fails with class not found: matlab.mixin.CustomDisplay. In Octave, only overloading the class’s own disp method customizes display. For enumeration classes, where the mixin cannot be used, the documentation points to overloading the disp function instead.

matlab.mixin.Scalar

The opposite customization is to forbid arrays. A class that derives from matlab.mixin.Scalar always behaves as 1-by-1: creating empty arrays is prohibited, concatenation is prohibited, and size returns [1 1]. The documentation gives hardware interfaces as the use case, where each instance has its own state and an array makes no sense. Scalar derives from matlab.mixin.indexing.RedefinesParen, whose parenthesis-indexing methods (parenReference, parenAssign, parenDelete, parenListLength) error by default; you can overload them to give obj(...) your own meaning.

classdef Thermocouple < handle & matlab.mixin.Scalar
    % One physical sensor channel; arrays of channels are not meaningful.
    properties
        Channel (1,1) double = 1
    end
end

With this class, [Thermocouple Thermocouple] and Thermocouple.empty raise errors (not run here; the message text varies by release). Since R2026a the specialized operators end, isempty, isscalar, length, ndims, numel and size are hidden methods; their behavior is unchanged.

Introspection of classes and objects

Query functions

Four functions answer most questions without metadata objects.

Call Result

properties(obj) or properties("ClassName")

Cell array of the names of non-hidden properties with public GetAccess, including inherited ones. For a scalar object, dynamic properties are included too; for an array, the properties of its class.

methods(obj) or methods("ClassName")

Names of the non-hidden public methods, including inherited ones. methods(obj,"-full") adds inheritance information, attributes and signatures.

events(obj) or events("ClassName")

Names of non-hidden events with public ListenAccess, including inherited ones. Every handle class has ObjectBeingDestroyed.

isprop(obj,"Name"), ismethod(obj,"name"), isa(obj,"ClassName")

Logical tests for a property, a method or class membership.

With no output argument, properties and methods print a list; with one, they return a cell array. Octave 11.3.0 on the Plate from above:

p = heatflow.Plate(4, 3, 0.01, 1e-4);
disp(isa(p, "heatflow.Plate"))
disp(isprop(p, "Alpha"))
disp(ismethod(p, "maxTemperature"))
props = properties(p)
meths = methods(p)
mc = metaclass(p);
disp(mc.Name)
1
1
1
props =
{
  [1,1] = Nx
  [2,1] = Ny
  [3,1] = Dx
  [4,1] = Alpha
  [5,1] = T
}

meths =
{
  [1,1] = Plate
  [2,1] = maxTemperature
}

heatflow.Plate

In MATLAB the methods list also contains the methods every class inherits (for a handle class, for example, delete, addlistener and notify), so the list is longer than Octave’s two entries. Octave 11.3.0 has no events function (it reports that events "is not yet implemented"). Use ismethod to test for a method and isprop for a property instead of searching these cell arrays with strcmp.

Metaclass objects

For attributes, defaults, descriptions and relationships, ask for the class’s metadata object. There are three equivalent ways to get a matlab.metadata.Class object:

  • mc = metaclass(obj) from an instance (or an array of instances; the result is always scalar);

  • mc = ?ClassName, the question-mark operator, which takes a class name written in the code and not a variable;

  • mc = matlab.metadata.Class.fromName("ClassName"), which accepts the name in a variable.

matlab.metadata.Class is a handle class that you cannot construct directly and whose properties are read-only. Its main properties:

Property Content

Name, Description, DetailedDescription

Class name (with namespace), and the short and long help text taken from the comments in the class definition.

Hidden, Sealed, Abstract, Enumeration, HandleCompatible, ConstructOnLoad, RestrictsSubclassing

The class attributes from the classdef line, as logical values.

PropertyList, MethodList, EventList

Arrays of matlab.metadata.Property, matlab.metadata.Method and matlab.metadata.Event objects, including inherited public and protected members. EventList is empty for value classes.

SuperclassList, InferiorClasses

matlab.metadata.Class arrays.

EnumerationMemberList

matlab.metadata.EnumerationMember objects, with Name and Hidden.

Namespace, Aliases

The containing matlab.metadata.Namespace object (empty when the class is not in a namespace), and any aliases.

flowchart LR A["metaclass(obj), ?ClassName, Class.fromName(name)"] --> C["matlab.metadata.Class"] C --> PL["PropertyList: Property objects"] C --> ML["MethodList: Method objects"] C --> EL["EventList: Event objects"] C --> SL["SuperclassList: Class objects"] C --> EM["EnumerationMemberList"] F["metafunction(name) R2026a"] --> FN["matlab.metadata.Function"] FN --> SG["Signature: CallSignature"] SG --> AR["Inputs and Outputs: Argument objects"] ML --> SG

The following listing prints each property of Plate with its access attributes. The element objects expose the attributes of the properties block as logical or enumeration-like values (for example Dependent, Constant, Hidden, GetAccess and SetAccess); check the exact property names on the matlab.metadata.Property page before relying on them in code. Not run here: Octave 11.3.0 returns the metaclass property list as a plain cell array instead of metadata objects, so {mc.PropertyList.Name} fails there.

mc = ?heatflow.Plate;
for k = 1:numel(mc.PropertyList)
    prop = mc.PropertyList(k);
    fprintf("%-6s Dependent=%d Hidden=%d\n", prop.Name, prop.Dependent, prop.Hidden);
end

Use the metadata when writing tools: a generic serializer that walks PropertyList and skips Dependent or Transient members, a documentation generator that prints Description for each member, or a test that asserts a class is Sealed. For ordinary code, prefer plain calls to the class’s methods; introspection hides the dependency from readers.

The R2024a rename: meta.* became matlab.metadata.*

Before R2024a the metadata classes lived in the meta package (meta.class, meta.property, meta.method, meta.event, meta.package). Since R2024a the documented names are matlab.metadata.Class, matlab.metadata.Property, matlab.metadata.Method, matlab.metadata.Event and matlab.metadata.Namespace, matching the rename of packages to namespaces in the same release. The matlab.metadata.Class page states "Renamed from meta.class in R2024a". New code should use the new names; code that must run on R2023b or earlier has to keep the old ones, and a ?ClassName or metaclass(obj) call returns the right object under either name, so those two entry points are the portable choice.

Function metadata with metafunction (R2026a)

obj = metafunction(identifier) returns a matlab.metadata.Function (for a function or constructor) or matlab.metadata.Method object (for a class method, written "MyClass/myMethod"; for a local function, "myFunction>myLocalFunction"). The object gives the help text, the full path and namespace, and a Signature property, a matlab.metadata.CallSignature, whose Inputs and Outputs are matlab.metadata.Argument arrays describing required or optional status, default values and validation. Two further options, Arguments={val1,...} and ArgumentTypes=["type1",...], describe which overload MATLAB would choose for given argument values or types.

The documentation notes that detailed argument and validation information requires the function to use an arguments block; for other functions the information is limited (see Argument Validation). An illustrative example (not run here, since it needs R2026a):

function dt = stableTimeStep(dx, alpha)
% stableTimeStep  Largest stable explicit time step in seconds.
    arguments
        dx (1,1) double {mustBePositive}
        alpha (1,1) double {mustBePositive}
    end
    dt = dx^2 / (4*alpha);
end
mf = metafunction("stableTimeStep");
disp(mf.Name)
disp(mf.Description)
numInputs = numel(mf.Signature.Inputs)

Here mf.Description is the first help line from the function file and numInputs is 2. Release changes around this interface: in R2026a the Method class gained Signature, and its InputNames and OutputNames properties are no longer recommended; from R2026b OutputNames returns varargout for outputs declared in an arguments block, so read Signature instead. R2026a also added namespaceFunctions and namespaceClasses, which return matlab.metadata.Function and matlab.metadata.Class arrays for the members of a namespace (see Namespaces and Class Folders), and made matlab.metadata.Namespace.fromName and getAllNamespaces no longer recommended.

Pitfalls

Mistake What to do

A constructor that requires arguments

Assigning a(5) = obj or calling createArray calls the constructor with no arguments to fill the array and errors if it cannot. Guard the body with if nargin > 0.

plates.Alpha = 2e-4 to set a property on every element

Not allowed. Loop, or use a left-side comma-separated list with deal.

x = plates.Nx expecting a vector

The result is a comma-separated list. Use [plates.Nx], or {plates.T} for unequal sizes.

A method that indexes obj.Prop directly

It fails for arrays. Write [obj.Prop] or loop over numel(obj).

Expecting isa(x,"double") to reject a subclass of double

isa is true for subclasses. Compare class(x) with strcmp for an exact match.

Overriding disp or display in a CustomDisplay subclass

They are sealed. Override getHeader, getPropertyGroups, getFooter or a state handler, with Access = protected.

Customizing display for an enumeration with CustomDisplay

Not supported; the documentation points to overloading disp.

Searching properties(obj) for a hidden or non-public property

Hidden and non-public members are not listed. Use metaclass(obj).PropertyList, which includes protected members.

Using meta.class in new code

Renamed to matlab.metadata.Class in R2024a; use metaclass or ? for code that spans releases.

Where older books differ

Books written before 2013 describe object display only by overloading disp and display and some also teach overloading subsref, subsasgn and numel to customize indexing. Overloading still works, but matlab.mixin.CustomDisplay (R2013b) is the documented way to customize display, and matlab.mixin.Heterogeneous is the documented way to build mixed arrays. Older books also describe function-syntax classes (an @ folder with a constructor that calls class); that style does not carry over to classdef, and R2026a announced the future removal of function-syntax classes.

Introspection in books is written with the meta package: meta.class.fromName, ?ClassName, and meta.property. The ? operator and metaclass are unchanged, but the class names changed in R2024a (above), and createArray (R2024a) and metafunction (R2026a) appear in no book published before 2024. A book that says MATLAB cannot create empty arrays of a user class, or cannot ask a function for its argument types at run time, predates ClassName.empty and metafunction.