Classes and objects in matlab: the quick and dirty way
Kevin Murphy, 19 November 2005
I found a really easy way to implement classes in matlab, which makes
them act just like structs, but with proper function name overloading.
I explain this briefly below.
For more details, see
mathworks
official documentation on objects/classes.
See also some
guidelines from CUED.
For some examples of software systems that use classes/ objects,
see BNT (Bayes net toolbox)
or
Spider
(toolbox for iid classification and regression problems).
Why bother with objects/ classes?
There are several advantages to using matlab classes.
Multiple versions of the same function
With classes, you can implement 2 or
more versions of the same function and give them the same name, and
let matlab decide which version to use.
(This is called dynamic dispatching.)
Normally if you have 2
functions with the same name, both on your path, only one is visible
(this is called name-space pollution).
But if you use classes, you can have private name spaces.
Suppose you have two classes, one called 'dummy' and the other
'dummy2'. Both implement a function called 'gradient'.
Then the following sequence will call dummy/gradient.m
d = dummy(...) % construct an object
gradient(d, ...)
whereas the following sequence will call dummy2/gradient.m
d = dummy2(...) % construct an object
gradient(d, ...)
Encapsulating internal state
Often we want to pass a function such as 'gradient' to another function,
such as 'minimize', but 'gradient' needs lots of extra arguments.
These can be passed in to minimize using varargin (as in the
optimization toolbox), but a cleaner method is to make an object, such
as one of type dummy, that contains all the data it needs inside of
itself. Then just pass dummy to 'minimize', and when it calls
'gradient', the gradient function will have acccess to the internal
state of the dummy object.
(Note: in matlab 7, it is finally possible to make
functions
with lexical scoping, thus somewhat reducing this particular
reason to use objects.)
How to write your own class
Suppose your class is called 'dummy'.
You can download a minimal set of files to implement any class such as
this
here.
We will explain them below.
- You need to make a @dummy directory.
All methods should be .m files within this directory.
You can hide subfunctions in the private subdirectory.
-
You must define a constructor function called dummy.m. We will
explain this below.
Type clear classes (rather than restarting matlab)
if you change a class constructor definition.
- It's a good idea to define a display.m function.
This version will just print out the object as if it were a named struct.
function display(obj)
disp(sprintf('%s object', class(obj)))
disp(struct(obj))
- It's a good idea to define subsref.m. The following will
let you access the fields of an object as if it were a struct (ie. all
fields are public).
function B = subsref(A, S)
B = builtin('subsref', A, S);
- It's a good idea to define subsasgn.m. The following will
let you change the fields of an object as if it were a struct (ie. all
fields are public).
function B = subsasgn(A, S, B)
B = builtin('subsasgn', A, S, B);
- It's a good idea to make a demo.m or test.m function.
There are usually tons of files with this name. But if you make it a
method, you can be sure you are calling the right one as follows
demo(dummy)
This creats an object of class dummy with default arguments; this is
essentially an empty struct with the tag 'dummy'. Then matlab knows it
should call dummy/demo.m. The demo function can then do whatever it
wants; typically it will ignore its argument, and create a new object
with sensible parameters.
Constructor
The constructor should follow the outline below.
Taking shortcuts here will cause problems (eg you will not be able to
save/load your objects - a mistake I made in BNT.)
function obj = dummy(varargin)
% Constructor for a dummy class object.
% You must always pass one argument if you want to create a new object.
if nargin==0 % Used when objects are loaded from disk
obj = init_fields;
obj = class(obj, 'dummy');
return;
end
firstArg = varargin{1};
if isa(firstArg, 'dummy') % used when objects are passed as arguments
obj = firstArg;
return;
end
% We must always construct the fields in the same order,
% whether the object is new or loaded from disk.
% Hence we call init_fields to do this.
obj = init_fields;
% attach class name tag, so we can call member functions to
% do any initial setup
obj = class(obj, 'dummy');
% Now the real initialization begins
obj.field1 = rand(2,3);
obj.field2 = varargin{1};
%%%%%%%%%
function obj = init_fields()
% Initialize all fields to dummy values
obj.field1 = [];
obj.field2 = [];
Example of use
>> d=dummy(55)
dummy object
field1: [2x3 double]
field2: 55
>> demo(dummy)
this is a cool demo
>> d.field1=22
dummy object
field1: 22
field2: 55
>> d.field2
ans =
55