Classes and OOP
MATLAB has had object-oriented features since the 1990s; the modern system — the MATLAB Class Definition Object System, or MCOS — was introduced in R2008a and is the one all current code uses. A class is declared in a .m file with the keyword classdef; the file’s name must match the class’s name. The system supports properties with validation, methods (including constructors and operator overloads), events, and enumerations. Crucially, classes choose between value semantics (the default; instances copy on assignment) and handle semantics (instances are references; assignment shares the object). The distinction shapes every aspect of class design and is the substance of MATLAB OOP that distinguishes it from systems like Python’s or Java’s.
A minimal class
% File: Point.m
classdef Point
properties
x (1, 1) double = 0
y (1, 1) double = 0
end
methods
function obj = Point(x, y)
if nargin >= 1
obj.x = x;
end
if nargin >= 2
obj.y = y;
end
end
function d = norm(obj)
d = hypot(obj.x, obj.y);
end
function obj = translate(obj, dx, dy)
obj.x = obj.x + dx;
obj.y = obj.y + dy;
end
end
end
A user constructs and uses the class:
p = Point(3, 4);
p.norm % 5
q = p.translate(1, 1); % returns a NEW Point at (4, 5)
p.x % still 3 — value semantics
q.x % 4
The properties have size and class validation ((1, 1) double) and default values. The constructor accepts variable numbers of arguments — the if nargin >= pattern is the conventional way before the arguments block — and assigns each property. The method translate returns a new object with the translated coordinates; the line q = p.translate(1, 1) replaces q with the new object. The original p is unchanged: this is value semantics.
Value vs handle classes
A classdef without inheritance from handle is a value class. Assignment copies; modification through a method requires the method to return a new object that the caller assigns back. The semantics is simple and predictable; it matches MATLAB’s primitive types.
A class that inherits from the built-in handle is a handle class. Assignment shares the object — every reference to the same handle is the same instance. A method that modifies the object’s properties modifies all references to it:
% File: Counter.m
classdef Counter < handle
properties
n (1, 1) double = 0
end
methods
function increment(obj)
obj.n = obj.n + 1; % mutates the shared object
end
end
end
c = Counter();
d = c;
c.increment();
d.n % 1 — c and d are the same object
The choice is design-driven:
- Value semantics is appropriate for mathematical objects with no identity — points, polynomials, geometric shapes, statistical distributions. Their value is their state; copies are equivalent.
- Handle semantics is appropriate for objects with identity — file handles, GUI components, network connections, simulation entities. The identity matters; the object is a thing in the world.
Most of the built-in MATLAB classes that wrap external resources — figures, axes, timers, listeners, file handles, deep-learning networks, parallel pool workers — are handle classes.
Properties
A property is declared in a properties block. Multiple blocks may set different attributes:
classdef Sensor < handle
properties
Name (1, 1) string
SampleRate (1, 1) double {mustBePositive} = 100
end
properties (Access = private)
Buffer (1, :) double
end
properties (Constant)
MAX_RATE = 10000
end
properties (Dependent)
SampleInterval
end
methods
function v = get.SampleInterval(obj)
v = 1 / obj.SampleRate;
end
end
end
The principal attributes:
Access—public(default),protected,private.Constant— single value shared by all instances; assigned in the property block; cannot be changed.Dependent— computed by a getter; not stored. The getter is a method namedget.PropertyName.SetObservable— fires aPostSetevent on assignment; allows listeners.Hidden,Transient,NonCopyable,Abstract— finer control for advanced use.
Methods and the dispatch convention
Methods are declared in a methods block. The conventional first parameter is the object — typically named obj, this, or self. MATLAB dispatches on the first argument; calling obj.method(x) is equivalent to method(obj, x), and both forms work.
classdef Vector
properties; x; y; z; end
methods
function obj = Vector(x, y, z); obj.x = x; obj.y = y; obj.z = z; end
function d = dot(a, b); d = a.x*b.x + a.y*b.y + a.z*b.z; end
function n = norm(obj); n = sqrt(obj.dot(obj)); end
end
end
u = Vector(1, 2, 3);
v = Vector(4, 5, 6);
u.dot(v) % 32 (method-call form)
dot(u, v) % 32 (function-call form, same dispatch)
The function-call form is the basis of operator overloading: a class that defines a method named plus(a, b) becomes addable with a + b. The reserved method names — plus, minus, times, mtimes, rdivide, ldivide, eq, ne, lt, le, gt, ge, subsref, subsasgn, disp, display, end, numel, size, length — correspond to specific operators and built-in functions.
Inheritance
A class inherits from another by listing it after <:
classdef ColoredPoint < Point
properties
Color (1, 3) double = [0 0 0]
end
methods
function obj = ColoredPoint(x, y, c)
obj@Point(x, y); % call superclass constructor
obj.Color = c;
end
function d = norm(obj)
d = norm@Point(obj); % call superclass method
% could do something more here
end
end
end
Multiple inheritance is permitted but rare; most useful classes inherit from handle and possibly from one other base class. The abstract attribute on a method declares that subclasses must provide an implementation.
Constructors
The constructor is a method with the same name as the class. It must return the constructed object (the first output). The implicit construction — when properties have defaults and the class has no constructor — is fine for many small classes; an explicit constructor is needed when arguments must be processed.
The R2019b arguments block applies to constructors:
classdef Sensor < handle
properties
Name (1, 1) string
SampleRate (1, 1) double = 100
end
methods
function obj = Sensor(name, opts)
arguments
name (1, 1) string
opts.SampleRate (1, 1) double {mustBePositive} = 100
end
obj.Name = name;
obj.SampleRate = opts.SampleRate;
end
end
end
s = Sensor("temp1", 'SampleRate', 200);
Events and listeners
Handle classes can declare events and notify listeners:
classdef Counter < handle
events
Tick
end
properties
n (1, 1) double = 0
end
methods
function increment(obj)
obj.n = obj.n + 1;
notify(obj, 'Tick');
end
end
end
c = Counter();
addlistener(c, 'Tick', @(src, evt) disp("tick"));
c.increment(); % prints "tick"
The mechanism is the basis of MATLAB’s GUI callbacks and of the observer-style designs in Simulink’s stateflow runtime.
Enumerations
A classdef can declare a finite enumeration:
classdef Direction < int32
enumeration
North (0)
East (1)
South (2)
West (3)
end
end
d = Direction.North;
class(d) % 'Direction'
int32(d) % 0
The members are constants of the class. Enumerations interact nicely with switch and with argument-validation blocks ({mustBeMember(x, "Direction")}).
A note on style
MATLAB classes follow conventions that differ subtly from those of Java or Python:
- Property names are conventionally PascalCase (
SampleRate), not camelCase. - Methods are conventionally camelCase (
addSample), but the standard library is inconsistent. - The first method argument is conventionally
obj, butthisandselfare also seen. - Operator overloads are common and idiomatic — a
Vectorclass withplus,minus,times,mtimesis a small thing to write and a great convenience to use. - Deep hierarchies are uncommon. Most MATLAB code uses shallow inheritance and composition.
For more elaborate object-oriented work — abstract base classes, sealed classes, mixins, dynamic properties — the MathWorks documentation page Defining Classes is the canonical reference.