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.
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 anyifblock. -
A constructor may call only its direct superclasses. If
Cderives fromBandBfromA, thenCcannot initialise the properties ofA;Bmust 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 |
Redefine |
The subclass method has its own body and never calls the superclass one. |
Template method |
The superclass declares a public method in a |
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
Abstractclass attribute, writtenclassdef (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 ... endblock, and it cannot have anargumentsblock. -
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
Abstractand with the sameSetAccessandGetAccess. -
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) Nameallows 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 asSealed. 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 |
Method |
Private in the defining class, the same definition everywhere, redefined by the subclass (so neither is |
Event |
Private |
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 ordinaryDirichletBCarray, 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
Sealedin the array’s class, so every element has the same definition. Overridable methods such asapplyare called on one element at a time, with the element retrieved by indexing. -
Heterogeneous classes are handle-compatible;
matlab.mixin.Heterogeneousalso has methods for defining the default object and converting objects that are not members.
Pitfalls
-
Conditional superclass call. Calling
obj@Super(...)inside anifis not allowed. Compute the arguments in theifand 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.abstractDetailson 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,Sealedand 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.