Object-oriented programming with Matlab
Why?
Object-oriented programming is a popular mode of working and is supported by Java, C++ and many other modern languages. It's claimed that it makes code easier to read and maintain. Furthermore, an object-oriented approach is in many cases more natural and appeals more to human cognition than other methodologies.
What?
In object-oriented programming you invent new types (called classes) designed to suit your task. These types are more sophisticated than simple variables or arrays - they can have functions (called methods) too. Just as you can create variables of a standard type (like a double in fortran) so in object-oriented programming you can create an object of a certain class, and you can redefine what '+' etc does when applied to these new objects.
Some important object-oriented (O-O) concepts are
- Objects and messages - in a procedural language like Fortran 77 data is passed around from routine to routine and there's no special relationship between the data and the routines that operate on it. In an O-O language, messages are sent to objects and the object is trusted to do what it's told, operating on the data held within it.
- Encapsulation - it's considered a good idea to keep together data and the routines which operate on that data, and to tightly control which routines are allowed to access the data (information hiding)..
- Code reuse - if you want to create a object that's like an existing object, you can use the existing object as a base for the new object. This is known as Inheritance.
The aim is to create objects that have tightly related parts but few connections with anything else. As an analogy consider a lightbulb: as long as it has a standard interface other components don't have to worry about how it's designed internally, and the lightbulb can easily be replaced by one that's internally very different.
How?
CUED's 2nd year C++ course mentions classes. The principles of Matlab's classes are similar. See the Object-Orientated Programming User Guide details. The classdef keyword is used to define a new class. Classes can have data (properties in Matlab) and functions (or Methods). Let's create a class to deal with colours. If you put the following into a file called colour.m
classdef colour properties red green blue end end
you can then type c=colour to create an object called c of that class, with 3 fields. It would be useful to be able to set the colour components when we create the object. To do that we need to write constructors - special methods that are used when creating objects. Here's an updated colour.m file with a constructor.
classdef colour properties red green blue end methods function c = colour(varargin) %COLOUR Colour class constructor switch nargin case 0 % No argument - set default colour c.red = 0; c.green=0; c.blue=0; c = class(c,'colour'); case 1 % 1 argument - if it's a colour object, copy to a new object if (isa(varargin{1},'colour')) c = varargin{1}; else % assume the arg is a number and set all the components c.red = varargin{1}; c.green=varargin{1}; c.blue=varargin{1}; c = class(c,'colour'); end case 3 % 3 arguments. Assume that they're the red, green and blue values c.red =varargin{1} ; c.green=varargin{2}; c.blue=varargin{3}; c = class(c,'colour'); otherwise error('Wrong number of input arguments') end end end
Another important method is display which is called when the
object is output as text.
It
produces output that's in the same form as standard MATLAB output: the
variable name is displayed followed by an equal sign, then a blank line,
then a new line with the values.
function display(c)
% COLOUR/DISPLAY
disp(' ');
disp([inputname(1),' = '])
disp(' ');
disp([' ' 'Red=' num2str(c.red) ', Green=' num2str(c.green) ', Blue=' num2str(c.blue) ])
disp(' ');
When that's added as a method, you can test by creating objects in various ways -
colour1=colour(1,2,3) colour2=colour(colour1) colour3=colour
(note that these lines don't end with semicolons, so the display method is called) and then try
colour4=colour(6,5)
which should print an error message because the number of arguments (nargin in the code) is unsupported by the code.
Other Class methods
Adding 2 of these colour objects together produces an error message, but you can make the '+' operator work with these new objects by creating a plus method. The following one produces a colour whose components are the average of the constituents' components. The code is written so that it will still work even if one of the operands is a number - the c1 = colour(c1) line has no effect if c1 is already a colour, but will convert c1 to a colour if it's a number.
function r = plus(c1,c2) % COLOUR/PLUS Implement '+' for colours. c1 = colour(c1); c2 = colour(c2); r= colour ( (c1.red+c2.red)/2,(c1.green+c2.green)/2,(c1.blue+c2.blue)/2);
With this code installed, typing
colour5=colour1+colour3
will produce a blend. If you want to be able to brighten a colour by a given factor, you could add a brighten method
function r = brighten(c,f) % COLOUR/BRIGHTEN r= colour (c.red*f, c.green*f, c.blue*f);
and once you've installed it you can call colour5=brighten(colour5,3) to brighten colour5 by a factor of 3.
To find out which methods exist for a class, use the methods command - e.g. methods('colour').
When?
Not all tasks are suited to an object-oriented approach, but in a big project it's useful to be able to hide data, and keep data close to related routines. It also helps with name-clash issues. As in C++, it's possible to have 2 or more functions with the same name as long as they have different types of objects as arguments. The brighten function created above is invoked if the first argument is a colour object, otherwise the standard brighten function is called.
Handle Classes
Create a file called valueInt.m containing the following code
classdef valueInt properties myValue=0; end methods function v = valueInt(val) v.myValue=val; end end end
This creates a class with one piece of data and one contructor to set that data to an initial value. Type
vi1=valueInt(7); vi2=vi1; vi2.myValue=999; vi1.myValue
The answer 7 will be printed out, which should come as no surprise - 2 objects are created. Now create a file called handleInt.m containing the following code
classdef handleInt < handle properties myValue=0; end methods function v = handleInt(val) v.myValue=val; end end end
This differs from the previous code only in its first line. handleInt is "derived from" the handle class and thus inherits the handle class's characteristics. Run the following -
hi1=handleInt(7); hi2=hi1; hi2.myValue=999; hi1.myValue
The output will be 999 because hi2 is an alias for hi1 - there's only one underlying object.
See Also
- Object Oriented Programming in Matlab (in particular the Handle Superclass and Events sections)
- Mathworks' Object-Oriented Programming document