Inheritance and Abstract Classes

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. Subclassing, abstract classes and sealed classes have existed since the classdef syntax arrived in R2008a, AllowedSubclasses is documented as a class attribute for sealed hierarchies, and matlab.mixin.Heterogeneous was introduced in R2011a. The examples that were run use Octave 11.3.0, whose classdef support is partial: it accepted the subclass syntax, explicit superclass calls, Abstract and Sealed class attributes, but rejected an abstract methods block and has no matlab.mixin.Heterogeneous. Those cases are labelled "not run here" and checked against the R2026b documentation instead.

Inheritance lets a class reuse the properties and methods of another class and specialise them. The class that is extended is the superclass, the one that extends it is the subclass, and a subclass object is a superclass object, so it can be passed to any function that accepts the superclass. The documentation introduces class hierarchies as a way to "reuse functionality by factoring out commonalities into superclasses". The class syntax is on classdef Basics, the difference between value and handle classes on Value and Handle Classes, and members on Properties and Methods. A subclass inherits the superclass kind: a subclass of a handle class is a handle class.

The running example: boundary conditions

The heatflow scenario (The heatflow scenario) has so far described the edge behaviour of a plate with the enumeration heatflow.BoundaryKind (see Enumerations). An enumeration names the choices, but it cannot carry data such as the fixed temperature of a Dirichlet edge, and every switch over it must be edited when a new kind is added. A class hierarchy is the alternative: each kind of boundary becomes a class that knows how to apply itself to a temperature matrix.

classDiagram class BoundaryCondition { <<abstract>> +string Name +describe() +apply(T)* } class DirichletBC { +double Value +apply(T) +describe() } class NeumannBC { +apply(T) } class PeriodicBC { +apply(T) } BoundaryCondition <|-- DirichletBC BoundaryCondition <|-- PeriodicBC BoundaryCondition <|-- NeumannBC

The diagram is a design sketch for this page, not part of the shared heatflow API. The names are unqualified for brevity; in a real package they would be heatflow.BoundaryCondition and so on, and the superclass would be written with its namespace (see Namespaces and Class Folders). PeriodicBC is drawn but not implemented below.

Subclass syntax

Write the superclass after a < on the classdef line:

classdef DirichletBC < BoundaryCondition
    % ...
end

The documentation gives the general forms as classdef ClassName < SuperClass and, for several superclasses, classdef ClassName < SuperClass1 & SuperClass2. Class attributes are not inherited: a subclass of an Abstract class is concrete unless it declares itself abstract or leaves an abstract member unimplemented. A subclass can also derive from a built-in class such as double; the documentation’s PositiveDouble < double example validates the input, then calls the superclass constructor with obj = obj@double(data).

Superclass constructors

If a subclass constructor does not call the superclass constructor, MATLAB calls it for you with no arguments, so the superclass must then accept a call with no inputs. To pass arguments, or to control the order when there are several superclasses, call it explicitly with the @ operator:

obj = obj@SuperClass(args)

The rules in the documentation are:

  • The call must come before any other reference to the object.

  • It cannot be conditional. The page says to give default values to the inputs first (if nargin == 0) and to call the superclass constructor outside any if block.

  • A constructor may call only its direct superclasses. If C derives from B and B from A, then C cannot initialise the properties of A; B must do it.

  • A superclass in a namespace is named with it: obj@finance.Assets(args).

  • MATLAB does not guarantee the order in which several superclass constructors run unless you call them all explicitly from the most specific subclass.

A complete hierarchy

The superclass declares what every boundary must offer (apply) and supplies what they can share (Name and describe). In MATLAB:

% BoundaryCondition.m
classdef (Abstract) BoundaryCondition
    properties
        Name = "unnamed"
    end
    methods
        function obj = BoundaryCondition(name)
            if nargin > 0
                obj.Name = name;
            end
        end
        function describe(obj)
            fprintf("%s: %s\n",obj.Name,class(obj));
        end
    end
    methods (Abstract)
        T = apply(obj,T)    % no body, no end: only the signature
    end
end

Two concrete subclasses follow, each in its own file:

% DirichletBC.m
classdef DirichletBC < BoundaryCondition
    properties
        Value = 0
    end
    methods
        function obj = DirichletBC(value)
            obj = obj@BoundaryCondition("Dirichlet");
            obj.Value = value;
        end
        function T = apply(obj,T)
            T([1 end],:) = obj.Value;
            T(:,[1 end]) = obj.Value;
        end
        function describe(obj)
            describe@BoundaryCondition(obj);     % extend, do not replace
            fprintf("  fixed value %g\n",obj.Value);
        end
    end
end
% NeumannBC.m
classdef NeumannBC < BoundaryCondition
    methods
        function obj = NeumannBC()
            obj = obj@BoundaryCondition("Neumann");
        end
        function T = apply(obj,T)
            T([1 end],:) = T([2 end-1],:);       % zero gradient: copy the neighbour
            T(:,[1 end]) = T(:,[2 end-1]);
        end
    end
end

Octave 11.3.0 rejected the abstract methods (Abstract) block above with "external methods are only allowed in @-folders", so for the run the superclass was a concrete class whose apply raised an error, and the two subclasses were used unchanged. The driver script and the output it printed were:

d = DirichletBC(20);
n = NeumannBC();
d.describe();
n.describe();
T = magic(4);
disp(d.apply(T))
disp(n.apply(T))
disp(isa(d,"BoundaryCondition"))
bcs = {d, n};
for k = 1:numel(bcs), disp(class(bcs{k})); end

Octave 11.3.0 output (MATLAB layout may differ):

Dirichlet: DirichletBC
  fixed value 20
Neumann: NeumannBC
   20   20   20   20
   20   11   10   20
   20    7    6   20
   20   20   20   20
   11   11   10   10
   11   11   10   10
    7    7    6    6
    7    7    6    6
1
DirichletBC
NeumannBC

describe of DirichletBC printed the superclass line first through describe@BoundaryCondition(obj), and NeumannBC, which did not define describe, used the inherited one. The cell array holds objects of two classes and calls to apply pick the right implementation for each: that is polymorphism by method dispatch.

Overriding and extending methods

A subclass overrides an inherited method by defining one with the same name. The documentation lists four patterns:

Pattern How it works

Extend

The subclass method does its own work and calls foo@Super(obj), as DirichletBC.describe does above.

Redefine

The subclass method has its own body and never calls the superclass one.

Template method

The superclass declares a public method in a Sealed methods block that calls protected step methods (step1, step2, step3). Subclasses override only the steps, so they change what each step does but not the order.

Implement an abstract method

A subclass supplies the body of a method that the abstract superclass left empty.

A method that overrides another must use the same Access attribute as the superclass method. When a superclass method is passed a subclass object, MATLAB dispatches the inner calls to the subclass versions, which is what makes the template method pattern work. The method in the template, with a sketch in the same words as the documentation (not run here):

classdef Solver
    methods (Sealed)
        function run(obj)           % fixed order, cannot be overridden
            prepare(obj)
            advance(obj)
            finish(obj)
        end
    end
    methods (Access = protected)
        function prepare(obj), end  % subclasses override these
        function advance(obj), end
        function finish(obj), end
    end
end

Abstract classes and members

An abstract class describes what a family of classes has in common but cannot be instantiated. According to the documentation, a class is abstract when it has any of:

  • the Abstract class attribute, written classdef (Abstract) Name;

  • an abstract method, declared in a methods (Abstract) block;

  • an abstract property, declared in a properties (Abstract) block.

Declaring an abstract member sets the class attribute to true automatically. The rules for members are:

  • An abstract method is only a signature. Do not use a function ... end block, and it cannot have an arguments block.

  • A concrete subclass is not forced to use the same argument names or counts, although it generally should.

  • A subclass that does not implement every inherited abstract member is itself abstract.

  • Abstract properties cannot have access methods or initial values. The concrete subclass must redefine the property without Abstract and with the same SetAccess and GetAccess.

  • An abstract class may have concrete members and need not have any abstract ones.

Trying to create an instance of an abstract class is an error. Octave 11.3.0 accepted the (Abstract) class attribute and refused to construct it, with this message (MATLAB’s wording differs, not run here):

classdef (Abstract) A
  methods
    function obj = A(), end
  end
end

a = A();
cannot instantiate object for abstract class 'A'

Two introspection tools are in the documentation. The Abstract property of the metaclass, mc = ?AbsClass; mc.Abstract, tells whether a class is abstract, and matlab.metadata.abstractDetails('SubAbsClass') lists the abstract members that a subclass still has to implement together with the classes that define them (not run here). Use them when a concrete subclass refuses to instantiate and you do not know which member it forgot.

Restricting inheritance: Sealed and AllowedSubclasses

Inheritance is open by default. Two class attributes close it:

  • classdef (Sealed) Name allows no subclasses at all. A sealed method (methods (Sealed)) cannot be overridden, which is how the template-method pattern fixes the order of the steps.

  • classdef (AllowedSubclasses = ?ClassName) Name, or a cell array of such references, names the only classes that may derive from it. An empty cell array is the same as Sealed. Allowed classes must be written as a ? followed by the fully qualified name; the documentation says the value may not contain any other expression. Listing a class does not require it to exist or to be a subclass, and a name that MATLAB cannot find when loading is dropped silently; if none is found the class is effectively sealed.

Together they make a sealed hierarchy: a closed set of known classes below an abstract superclass. It is a good fit for the three boundary kinds, because the solver knows there will be no fourth one added by somebody else:

classdef (AllowedSubclasses = {?DirichletBC, ?NeumannBC, ?PeriodicBC}) BoundaryCondition
    % ...
end

classdef (Sealed) DirichletBC < BoundaryCondition
    % ...
end

Octave 11.3.0 checked the plain Sealed case: a classdef (Sealed) S, and a class S2 < S, which printed

'S2' cannot inherit from 'S', because it is sealed

The AllowedSubclasses form was not run here.

Multiple inheritance and mixins

A class can name several superclasses with &: classdef Stocks < finance.Assets & Taxable. The subclass inherits the properties, methods and events of all of them, and the constructor of each superclass should be called explicitly if you need arguments or a fixed order.

The price is the conflict rules. If two superclasses define a member with the same name, the documentation requires an unambiguous resolution:

Member Allowed when one of these holds

Property

Private SetAccess and GetAccess in all but one superclass, or the same definition in all of them (inherited from a common base).

Method

Private in the defining class, the same definition everywhere, redefined by the subclass (so neither is Sealed), sealed in exactly one superclass, or abstract in all and implemented by the subclass.

Event

Private ListenAccess and NotifyAccess, or the same definition everywhere.

The page itself warns that resolving conflicts "often reduces the value" of the approach, because a later version of a superclass can introduce a new clash. Its advice is to have only one unrestricted superclass and make every other superclass contain only abstract methods, methods defined by the subclass, or methods inherited from the unrestricted one. A class like this, with just a small set of capabilities, is called a mixin (as in the matlab.mixin namespace): you add it to a class to give it a behaviour such as matlab.mixin.Copyable. Not run here.

Heterogeneous arrays

An object array in MATLAB has one class, so ordinarily you cannot put a DirichletBC and a NeumannBC in the same array, which is what the cell array above worked around. The documentation notes that, unlike languages that store arrays of pointers, MATLAB can call a method on the whole array. To get both, derive the root of the hierarchy directly from matlab.mixin.Heterogeneous:

classdef (Abstract) BoundaryCondition < matlab.mixin.Heterogeneous
    properties
        Name = "unnamed"
    end
    methods (Sealed)
        function names = allNames(objs)     % callable on the whole array
            names = [objs.Name];
        end
    end
    methods (Abstract)
        T = apply(obj,T)
    end
end

bcs = [DirichletBC(20), NeumannBC()];   % one array, two classes
class(bcs)                              % "BoundaryCondition"
bcs.allNames()

Not run here: Octave 11.3.0 reported class not found: matlab.mixin.Heterogeneous. The rules from the documentation are:

  • The class of the array is the most specific common superclass of its elements. [DirichletBC(20),DirichletBC(0)] is an ordinary DirichletBC array, not a heterogeneous one, and adding an object of another class by indexing changes the class of the array.

  • Only concrete subclasses can be elements, but the root class can be abstract.

  • Dot access to a property works when the class of the array defines it (bcs.Name).

  • A method can be called on the whole array only if it is Sealed in the array’s class, so every element has the same definition. Overridable methods such as apply are called on one element at a time, with the element retrieved by indexing.

  • Heterogeneous classes are handle-compatible; matlab.mixin.Heterogeneous also has methods for defining the default object and converting objects that are not members.

Pitfalls

  • Conditional superclass call. Calling obj@Super(...) inside an if is not allowed. Compute the arguments in the if and call the constructor once, outside.

  • Forgetting an abstract member. The subclass becomes abstract silently, and the error appears only when you create an object. Run matlab.metadata.abstractDetails on it.

  • Overriding with different access. A method that overrides must keep the superclass Access.

  • Calling a grandparent constructor. A constructor can call only its direct superclasses.

  • Depth over composition. Deep hierarchies are rigid. When the relationship is "has a" rather than "is a" (a simulation has a boundary condition), hold the object in a property instead of subclassing.

  • Expecting attributes to be inherited. Abstract, Sealed and similar class attributes apply to the class that declares them only.

Where older books differ

The classic textbooks on MATLAB programming were written before classdef and describe object-oriented programming through the older @ClassName folders and struct-based constructors. Those mechanisms are not covered here; new code uses classdef, which brought the < syntax, Abstract, Sealed and handle classes (R2008a). Of the features in this page, AllowedSubclasses and matlab.mixin.Heterogeneous (R2011a) appear in no book of that period.