MATLAB® and Objects

Working with objects once a project becomes sufficiently complex makes it much easier to keep track of things. MATLAB® (a.k.a. MATrix LABoratory) is a nice product by a company called MathWorks that makes matrix manipulation incredibly easy. For us engineers and academics it is the standard goto, regardless if we need to rapid prototype some functionality or develop a complex and convoluted system. Only recently did I discover a whole hidden side of  MATLAB®: classes! And because I am an incredibly big fan of those beasts I decided to write a quick summary of how to use them.

A simple class and class handling

First of all, you can find a complete definition of MATLAB® classes here as I am not intending to explain all, but only the most important parts in this post. I also assume that you know what a class is and won’t get confused when I speak about an properties, methods and instances. So let’s get started! A class in MATLAB® is defined by the keyword classdef. Inside its definition a class has several sections in which it defines the properties and methods that the class provides. So an empty class might look like so:

classdef Vehicle
    properties
        % all your properties (i.e. 'class variables')
    end
    methods
        % all your methods (i.e. 'class functions')
    end
end

Now let’s add some more information to our vehicle class. First I’ll add a property holding the velocity (3d vector) of the vehicle, so nothing too complex. Also I’ll add a constructor and make a getter (function that will return the vehicle’s speed) and a setter (function that will apply the vehicle’s speed).

classdef Vehicle
    properties
        velocity
    end
    methods
        function [aVehicle] = Vehicle()
            aVehicle.velocity = [0; 0];
        end
        function speed = getSpeed(aVehicle)
            speed = sqrt( sum( aVehicle.velocity.^2 ) );
        end
        function [aVehicle] = setSpeed(aVehicle, speed, direction)
            x = speed * cos(direction);
            y = speed * sin(direction);
            aVehicle.velocity = [x; y];
        end
    end
end

Here, it is important to note that MATLAB® does not reference to the class at hand like some other object orientated programming languages do, i.e. by using the this or self pointer. That means each time you want to access a property from within the class definition you must pass the instance into the method; just like for the setSpeed() method. Additionally, if you want to modify a property of the class you can do so but all changes are done within the bounds of that method. To maintain the change, you have to let the method return the updated instance and reassign it where you called the method from. Sounds confusing? Let me help you with an example:

% the Vehicle class is saved in a file titled 'Vehicle.m' in the same directory

% first define an instance of 'Vehicle' called car
car = Vehicle();
% get the current speed (should be zero)
getSpeed(car) % I intentionally left out the semicolon
% next try changing the speed
setSpeed(car, 3.0, 0);
getSpeed(car)
% somehow the change did not stick?!?
% that's because we need to reassign the returned instance
car = setSpeed(car, 3.0, 0);
getSpeed(car)
% There you go...

That is because many things in MATLAB® are passed by value, hence preventing you from overwriting the original. Hence why you do the overwriting manually and explicitly. Yet you can change that behavior by defining a class with as a handle. Then any changes to the class’s properties by any class method saves that change to the same class, just like for other OOPLs.

classdef Vehicle < handle
    % All the rest of the class definition
end

Additionally, you can define static methods or class methods that are not called with a specific instance of the class. These methods do not perform operations on the individual object instance, but provide class wide functionality:

%...
    methods(Static)
    % static methods (i.e. 'functions') go here
    end
%...

Static methods are though called differently though:

% this calls a method on an instance (car) of Vehicle
paintVehicle(car, 'red');
% this calls a class method of 'static' method
Vehicle.updateRoadTax(71.50)

As you know, classes can inherit their functionality to subclasses, and that is the case in MATLAB®, too. Here, you can define a subclass like so:

classdef Car < Vehicle
    % class stuff...
end

Additionally, you can let a class inherit from multiple superclasses like so:

classdef Hovercraft < Vehicle & Boat
    % class stuff
end

Calling a superclass method is as easy as calling it from anywhere else in code. Yet if you overwrote the superclass method (e.g. setSpeed()) in your subclass, you need to explicitly address the superclass function. Let me give you an example with Car and Vehicle.

        % some class setup code...
        function [aCar] = setSpeed(aCar, kmh, direction)
            % Convert kmg -> speed
            speed = kmh * 1000 / 3600;
            aCar = setSpeed@Vehicle(car, speed, direction);
        end
        % more code...

Something similar is true for the constructor:

        % some class setup code...
        function aCar = Car()
            aCar@Vehicle();
        end
        % more code...

This allows you to for instance extend superclass behavior or assure values are set correctly.

More on properties

Now you may wonder why to use a getter and setter if you could also access the properties from the outside using the dot-notation. Well, you can change the access to

  • public  (default): the property is accessible by everyone
  • protected : the property is only accessible by the class and and inheriting sub-classes
  • private : the property is only accessibly by the defining class itself

To change the property access simply Access like so:

classdef Vehicle
    properties (Access = private)
        velocity
    end
end

When working with inheriting classes, you can access the superclass’s property as if it was part of the inheriting class. So you do not need to explicitly tell MATLAB® which superclass you want to access.

Anyhow, in the code below you can replace the KEYWORD with any of the following MATLAB® property attributes (I only listed some relevant ones…).

classdef Vehicle
    properties (KEYWORD = VALUE)
        % define properties...
    end
end
  • Abstract = false (default) or true: to define a root or prototype class that is never instantiated
  • Constant = false (default) or true: to define whether this property is a constant which is set during initialisation
  • Dependent = false (default) or true: to define whether a value is a computed property and not stored in memory
  • GetAccess or SetAccess = false (default) or true: to define the getting and setting accessibility of the property
  • Hidden = false (default) or true: to hide the property from the property inspector and prevent it from showing up in names window
  • Transient = false (default) or true: to prevent the property from being stored when the MATLAB® is saved

Eventsin MATLAB® classes

If it were up to me I’d say you know pretty much all that is required to code with MATLAB® classes. Yet there is that one extra thing that is pretty cool and it is called events. Events are like automatic methods that are called whenever something in the class happens. For instance when a parameter changes (these functions are also called property observers). Well, let me show you.

For one only handle classes can have observers and event handlers as the observer wouldn’t know which instance to observe (remeber they are copies by default). First let’s define the event that is triggered inside our Vehicle class:

classdef Vehicle < handle
    properties
        velocity = [ 0; 0 ];
    end
    events
        % Events are defined in here
        Accelerating
    end
    methods
        function aVehicle = setSpeed(aVehicle, speed, direction)
            x = speed * cos(direction);
            y = speed * sin(direction);
            newVelocity = [x; y];
            oldVelocity = aVehicle.velocity;
            delta = 1;
            % Here I define the event trigger by notifying the event...
            notify(aVehicle, 'Accelerating', AccelerationData(oldVelocity, newVelocity, delta));
            aVehicle.velocity = newVelocity;
        end
    end
end

Now we have not yet defined the event’s data class itself that will contain the data of the event when it’s triggered. So let’s do that now. Keep in mind that such a class capturing event data must inherit from an event.EventData object.

classdef (ConstructOnLoad) AccelerationData < event.EventData
    properties
        acceleration = 0;
        duration
    end
    methods
        function anAccelerationData = AccelerationData(oldVelocity, newVelocity, delta)
            anAccelerationData.acceleration = (newVelocity - oldVelocity) / delta;
            anAccelerationData.duration = delta;
        end
end

Now by itself this would not do much, but you can add a listener to look out for Accelerating events. You do that by attaching a listener to the just defined handler class like so:

% create a vehicle instance
car = Vehicle();
% add a listener to the car
addlistener(car, 'Accelerating', @accelerateHandler);

% then somewhere define the handler function itself
function accelerateHandler(eventSource, eventData)
    fprintf('The object was accelerating with %f m/s\n', eventData.acceleration);
    fprintf('The acceleration lasted %f seconds\n', eventData.duration);
end

How cool is that 😀

Leave a Reply

*
*