Loren on the Art of MATLAB

When to Create Classes in MATLAB 31

Posted by Loren Shure,

I’m pleased to introduce today’s guest blogger, Nausheen Moulana. Nausheen manages the teams responsible for the design and development of the MATLAB language. She shares her thoughts on when you might want to create classes in MATLAB.

Contents

The thing I like most about the MATLAB environment is the flexibility I have as a programmer to choose the function/API that I think is required for the task at hand. And what's neat is that if I don't find or like what comes "in-the-box", I can create my own.

The enhanced object-oriented programming capabilities in the R2008a release of MATLAB add some new tools to our programming toolbox. While I can still program with existing tools such as functions and scripts, here are some situations where creating a class makes good design sense.

Create a New Data Type

MATLAB, like most programming languages, has a set of primitive data types with a set of operations defined on them. However, there are situations when we may need to create our own data type. For example, I might want to use structure arrays to track employee information but want to restrict the addition of new fields or modification of the values associated with existing fields.

employee.age = 23;
employee.name = 'Jane';
employee.ID = 17;
employee(2) = struct('age',39,'name','Jerry','ID',45);
employee
employee = 
1x2 struct array with fields:
    age
    name
    ID

The problem I face is that the fields of structure arrays can be modified easily by assigning new values to them just like I can modify any variables that store primitive data types.

On the other hand, if the variable employee is an object, only functions I choose (as creator of the class) can modify the fields.

The ability to control access and modification of data is referred to as encapsulation. Designing a class facilitates encapsulation thereby improving the quality of my code since objects are robust to accidental modification.

At this point, I'd like to clarify the distinction between classes and objects. Classes are a mechanism to describe interfaces to the functionality with which users will interact whereas objects are concrete instances of a class with their own data and related operations. Classes are designed and objects are used.

Another reason I may want to create a new type is to extend or redefine operations on an existing type. For example, I may require integer arithmetic to wrap as opposed to saturate (which is what MATLAB does) on overflow. I may, in addition, require a sqrt function that works on integers which isn't implemented in MATLAB. I can address these requirements by subclassing from the appropriate integer class in MATLAB and overwriting the arithmetic operations such as +, -, .*, ./, .\ and .^ to wrap on overflow. I can also add a method to my new integer class that computes the sqrt for integer values. Subclassing facilitates code reuse thereby eliminating the need to create new capabilities from scratch.

NOTE: If you do choose to override an arithmetic operator like plus, be aware that you may have to overload other functions that may use plus to ensure they give the right answer.

Using MATLAB's external interface APIs and interoperability capabilities, I can connect to external systems be they external devices such as data acquisition tools or external libraries created using Java or Component Object Model(COM). A convenient way to interact with these systems is to design a class that manages data access and modification as well as provides sufficient control over the functionality in the external system that I'd like to expose in MATLAB. By designing a class, I will be able to add new behaviors as the libraries I interface with evolve without compromising compatibility. Also, if the external system is implicitly object-oriented then designing a class is the more natural way to present it in MATLAB.

An example in MATLAB of a class which interfaces with an external library is the timer functionality which uses Java's timer object (java.util.Timer).

% Create a timer object and set its
% execution mode to schedule timer events.
t = timer('TimerFcn','figure;imagesc(magic(5))','Period',1);
t.ExecutionMode = 'fixedrate';
% Set name of the timer
t.Name = 'MyTimer';
% Set the number of times to execute the callback function.
% In this example, the image of magic squares is drawn twice,
% once for each of the two events.
t.TasksToExecute = 2;
% Start the timer.
start(t)
% Stop and release the timer.
stop(t)
delete(t)

In this example, designing a class allowed me to reuse timer functionality available in Java while giving me the flexibility to present APIs in a manner that is familiar to users interacting with objects in MATLAB.

Note that when using new classes written in MATLAB 7.6, I don't need to explicitly call the delete method to remove an object from memory; MATLAB does this automatically when the object is no longer used. The ability for an object to clean up, via the destructor, when MATLAB determines that the object is no longer being used is just one of the many enhancements to the object-oriented capabilities in MATLAB 7.6.

Manage the Lifecycle of Variables

Generally MATLAB takes care of managing memory for me. For example, create a 50x50 matrix of doubles.

a = rand(50);
a = 5;

With the second assignment to a, MATLAB takes care of freeing the memory allocated in the previous statement without any user intervention. Whenever variables go out of scope, are modified, or are no longer used, MATLAB automatically releases the memory associated with these variables when these variables happen to be primitive types. However, if the variables are resources such as file handles, fonts, or represent other types, then MATLAB needs to transfer control to that object to release resources when the object is no longer used.

In some situations I may need to take additional action to explicitly manage the lifecycle of the variables that get created. By creating class destructors (the delete method), I can ensure that memory associated with a variable is freed up when the variable is no longer being used. For example, let's look at the memmapfile class in MATLAB. The memmapfile functionality creates an object that lets me map a file to memory whereby any operations that modify the object in memory have the effect of modifying the contents of the file on disk.

Here's how I can map a file named records.dat to a series of unsigned 32-bit integers and set every other value to zero via the data property in memory.

   m = memmapfile('records.dat', 'format', 'uint32', ...
                  'writable', true);
   m.data(1:2:end) = 0;

Since MATLAB does not explicitly allocate the memory for the data contained in the variable m, it cannot release the memory either (i.e., in this case, unmapping the mapped region in MATLAB's memory) when the memmapfile object goes out of scope or is modified via assignment, perhaps in a situation like this.

   m = rand(4);

If I exposed the memory mapping functionality directly, I would risk inadvertent memory abuse if users of this class do not programmatically unmap mapped regions. However, an object-oriented approach mitigates this situation since it provides the class control over the creation and destruction of objects.

Organize Code

Keywords in MATLAB 7.6 allow me to define my class and organize my code in a single M-file. By having properties, methods, and events defined in the same file, I can gain an insight into class data and operations relatively quickly. With methods, I also have the flexibility of separating the function definition from implementation. I do so by defining the methods in the file containing the class definition and implementing the methods in separate files. Depending on the number of methods my class has, keeping method implementation in separate files can reduce clutter in the class definition.

Summary

MATLAB 7.6 has significant enhancements to object-oriented capabilities that simplify the process of designing classes while providing sufficient functionality to handle your most complex class design. When programming, if you find yourself needing to do any one of the above, then you should consider designing a class. I'd love to hear when you've found creating classes to be useful. Let me know here.


Get the MATLAB code

Published with MATLAB® 7.6

31 CommentsOldest to Newest

I’m pleased to see Matlab 7.6 begins to support class inheritance directly. Creating a toolbox on certain domain always means designing complex class hierachy and it is rather inconvenient to do that in previous version.

Handle class is another surprise. It seems undocumented in previous version. Inquisitive user can find its trace in the source code of those “official” toolbox. Now it is exposed… It does provide easy access to implementation of by-reference semantic and notify-listener mechanism.

I find the OO support in Matlab to be really useful! I think nowadays it would be a real shame to have to miss out on the various qualities that OO provides, plus is means if I’m prototyping and then moving to/from another language (which may well also be OO), it makes my like a lot easier.

Whew! That was a lot of information Nausheen. Very informative post.

How often do you use classes within MATLAB? What % of the MATLAB community do you think use this feature?

I’ve never really used it myself, so I’m wondering who else out there uses it on a consistent basis.

Oh yes, another question:

Is “nested function” obselete if we already have “classdef”? (Because both can generate instances bearing some states…)

Quan –

As you can guess, it’s always hard to know how many people use any given feature in MATLAB. I won’t let that stop me from waving my hands around a bit, though. To start, we view two classes of users of the class system: class creators and object users.

We expect a sizable minority of MATLAB users to be class creators – primarily those who come with other OO programming experience, or fairly advanced users who recognize the need to extend their skills in order to develop more robust, scalable, and supportable applications. We tried to design the functionality to appeal to both of these groups. Early indicators are that this has worked, as we’ve heard a lot from users who are adopting the new way of developing OO code in MATLAB. The design is quite approachable, so I hope that we’ll be able to increase the number of users who want to create their own classes over time.

We expect a much larger percentage of our users to work with objects. We’ve been presenting objects for years with good success, and expect it to get even easier to work with objects as we build more using the new capabilities Nausheen writes about.

- scott

Peng-

Nested functions are not obsolete and remain an important feature of the MATLAB language. They can be used successfully alone or in conjunction with the new class system when it makes sense.

–Loren

-Loren

Your reply is exactly what I’m confused with: dose nested function mean instances with states?

If so, it no more than “syntax suger” of classdef.
If not, what’s the underlying concept of it? And can you give an example that we must use nested function instead of classdef?

-Peng

Peng-

Nested functions are not classes. They are simply functions that have a different scope for variables than ordinary functions; they do have state. As such, they can be used wherever appropriate.

Objects of a class are variables. They might have state or not, depending on how the class is created.

Neither one is a replacement for the other. Many examples of nested functions COULD be written by creating classes. But it’s not required for them and creating a class has potentially an extra programming overhead that just might not be required for the application.

I can’t give an example where you MUST use nested functions as there are many ways to solve any given problem, and they are just one tool of many that may feel natural to the programmer.

–Loren

-Loren

Thanks for your lenthy explaination…

Is there any conterpart of nested function in other programing language?

Or is nested function an orignial idea of MathWorks?

-Peng

Peng,

Constructs similar to nested functions exist in some other languages, e.g., LISP. They are sometimes referred to as closures.

–Loren

Hi Nausheen,

A few questions regarding oop in MATLAB. In my application domain m-code objects are far too inefficient.

1) Pre-allocation of object arrays in R2008a seem to be up-to 10 times slower than the equivalent structure array. Are there plans to speed this up in an upcoming release?

2) Getting and setting of properties seem to be up-to four times slower than the equivalent structure array. Are there plans to speed this up in an upcoming release?

3) Are there plans to be able to compile m-code objects into c-mex objects? How about objects as signals in simulink?

Hello,

I only just started using Matlab, and I have a few possibly silly questions below:

I was wanting to know if it is possible to completely seperate the implementation from the definition.

I perticular, is it possible to put the implementation of the constructor in a separate M-file?

Also, say I have an attribute foo and a “set” method, of the form “function self = set.x( self, val ) …”, can I put the implementation in a separate M-file?

Finally, is it possible to groupe the implementation of several methods in a sungle M-file?

Thanks,
O.

I have to echo Matthews comments (#11) and add that calling a method function is also slow. I very much like the new OOP Matlab structure and use it frequently. However in a number of cases in my (sample-based comms systems) sims I have to run parts of my code in for loops and cannot vectorize them. When calling a method function for an object 10,000+ times you really start to notice the overhead using classes. This has precluded me from using classes in whole areas of my code, which is unfortunate.

Matthew,
We are working continuously on improving performance and expect to release improvements in the future. Because property access can involve more work than struct field access (including listener notification, set-functions, and different levels of access), the worst-case time for property access will always be much slower than for struct fields. However, our goal is for property access to be equivalent to struct field access when the property is being used in an equivalent way.

O.,
The constructor and set functions must be included inside the classdef. Ordinary methods can be in their own separate files, but each file can only contain a single method.

Peng,
Nested functions and classes provide very different capabilities and are generally used for different purposes. There are some applications where a solution could be built using class definitions or nested functions, but that doesn’t make classes a substitute for nested functions in general. A class has access to objects based on those objects being instances of the class. A method is a simple function, not nested in any particular object and has the same access to any instance of its class. A method may work on many objects. A nested function handle has access to the variables defined in its function and one set of variables defined in the context of its outer function(s). Nested functions can directly access variables from multiple layers of outer functions. Methods access properties through objects. Nested functions can’t be used to encapsulate interactions among different objects of the same class, and classes can’t be used to create the same kind of variable scoping as nested functions.

Ol,

What Dave said is true, the constructor and set functions must be included inside the classdef file, but if I interpret your question correctly I believe you can do what you want. Your constructor and set functions must be defined inside the classdef file, but of course they can call other functions that contain the actual “guts” of the implementation.

classdef myclass1
  properties
    Data
  end
  methods
    function obj = myclass1(x)
      obj = callHelperFunctionForConstructor(obj, x);
    end
  end
end

callHelperFunctionForConstructor can be any function that’s visible from the scope of the myclass1 constructor — another function or method in this file, a function on the path, a function in this directory, a private function inside this directory, etc. For instance, if this function was in the current directory:

function obj = callHelperFunctionForConstructor(obj, x)
obj.Data = x.^2;

then obj = myclass1(5) would construct an object whose Data property contained 5^2, or 25. I can see some situations where I might make use of this type of pattern, but for the most part I’d put the implementation of an object I create inside the object’s classdef file. That way, there are fewer places to look if there’s a problem with the class implementation or if I want to enhance the class at some future time.

Hello Loren,

I’m trying to implement a simple List container class backed by a cell array. It seems that accessing a cell array as a property of an object is over two orders of magnitude slower than accessing one directly as a variable!

Consider:

classdef MyList > list_compare
Elapsed time is 0.094564 seconds.
Elapsed time is 0.000446 seconds.
>>

Any ideas?

Thanks!

- Daniel

Eh, looks like my code wasn’t properly escaped for HTML encoding. I modified it to pseudocode.

classdef MyList
properties
cellArray = cell(1000);
length = 0;
end

methods
function append(self, value)
self.cellArray{self.length + 1} = value;
self.length = self.length + 1;
end
end
end

tic
list1 = MyList();
for i = 1 : 1000
list1.append(‘foo’);
end
toc

tic
list2 = cell(100);
for i = 1 : 1000
list2{i} = ‘foo';
end
toc

Elapsed time is 0.094564 seconds.
Elapsed time is 0.000446 seconds.

Ok, one more time with proper formatting this time. Sorry.

classdef MyList
  properties
    cellArray = cell(1000);
    length = 0;
  end

  methods
    function append(self, value)
      self.cellArray{self.length + 1} = value;
      self.length = self.length + 1;
    end
  end
end

tic
list1 = MyList();
for i = 1 : 1000
  list1.append('foo');
end
toc

tic
list2 = cell(100);
for i = 1 : 1000
  list2{i} = 'foo';
end
toc

>> list_compare
Elapsed time is 0.094564 seconds.
Elapsed time is 0.000446 seconds.
>> 

Currently, MATLAB does bookkeeping whenever properties are modified to ensure that objects get destroyed properly when no longer used. This overhead is particularly large for cell arrays where every cell could contain a value of any type. We are working on ways to eliminate this overhead in the future.

Hi Daniel:

In order to create a List class, you need to subclass from the handle class. If you don’t do so, only copies of the instance properties cellArray and length will be updated each time your append method is executed. This is also why the performance is significantly poorer than it should be. You can subclass from handle as follows:

classdef MyList < handle

% everything else remains the same
end

The performance will still not be as good as direct cell assignment (list2{i} = ‘foo';) due to the overhead of calling a method (list1.append(‘foo’);). We are working on addressing this issue.

Hth,
Nausheen

Hello Loren

Question on nested classes, using the new class syntax: I have noticed such file structures in the MATLAB toolboxes, but in the documentation it is stated that an @ folder with new class syntax will shadow all @folders under it, making them invisible even to the top level class. I have also noticed some schema.m in at the non-@ folders, containing these nested @ folders. What is the trick, because I cannot get that nesting to work and the documentation is not clear on this aspect?

Cheers

JP

JP,

The code you are referring to with the schema.m files is part of experimental code that is not part of the official MATLAB Class System. At present, we do not provide support for classes in nested @-directories. However, you can make use of packages to create nesting relationships.

To create a package directory, use the + symbol as a prefix for the directory name. Then, within that directory you can place @-directories containing class definitions. You can also place additional (nested) package directories.

For example, given the following directories:

+pkg1/@Class1
+pkg2/+pkg2/@Class2

Class1 is a class contained within pkg1, and can be instantiated using the syntax:

>> obj = pkg1.Class1;

Class2 is contained within the package pkg2, which is itself nested within pkg1. To create an instance, use the following syntax:

>> obj = pkg1.pkg2.Class2;

Hope this helps -

Jennifer

Loren,

In this post you wrote:
“Another reason I may want to create a new type is to extend or redefine operations on an existing type. For example, I may require integer arithmetic to wrap as opposed to saturate (which is what MATLAB does) on overflow.”

I am interested in doing exactly this but don’t know how to extend or redefine the math operators. If this particular example has been implemented somewhere, could you point me to it?

I would like to set this (wrap on overflow) as the default behavior for math operators within my MATLAB session for all integer data types without affecting the behavior of these operators for any other data type. I wonder if this behavioral setting should be something that should be available under MATLAB > Preferences…

Thanks,

Peter

Hi Peter:

Here are some options you have to redefine operations on integers only.

1) You can wrap on overflow by adding your own arithmetic operators for example, a plus method for the uint8 data type. You can do so by creating and adding a new @uint8 directory to a directory your MATLAB path (..\myDir\@uint8). In this directory you can add a plus method which contains the following code:

function result = plus(A,B)
result = uint8(mod(double(A)+B,256));

The above is just an example, it doesn’t account for error handling and performance. You can find more information on the function names for MATLAB operators at:
http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/f1-6624.html
By doing this, you can still use the uint8 command to construct integers but MATLAB will now call your plus method instead of the default method that saturates on overflow.

2) You can subclass from a built-in integer type and redefine the operations you are interested in. Here’s an example from our documentation:
http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/brgze9_-1.html#brsk0i6

It’s generally good to associate different behaviors with different classes. By using the second approach, you can use uint8 for the default saturate behavior and your own myuint8 class for wrap behavior.

Nausheen

Hello Loren,

I want a new class (mytype) to seamlessly interface with existing classes (builtin, e.g. “double” and non-builtin datatypes from existing other 3rd party toolboxes, e.g. “anothertype”).
This seems easy to achieve when the first argument of a function is my new datatype e.g.

a=mytype(10);
b=anothertype(12);
a+b % calls @mytype/plus
b+a % calls @anothertype/plus — problem here

The last line is undesirable for me, since I would like to overload the plus function in such a way that @mytype/plus gets called if ANY of its arguments is of type “mytype”.
If I am not starting to modify the code of @anothertype/plus (which I do not want to touch), I did not see a possibility to influence the behaviour.

Is there any possibility to influence which function gets called for which combination of datatypes?

Thanks for any help in clarifying this,

Rainer

Hello Loren,

Regarding #23, I would like to subclass ‘double’ to a +mypackage/@double to redefine operators such as ctranspose and mtimes.

But unless the @double dir lies directly in one of the dirs in *path*, Matlab seems unable to find it. E.g. ‘which mtimes’ will not find +mypagkage/@double/mtimes.m even if it exists and is declared in +mypackage/@double/double.m

Is that intended behaviour to prevent the users’ monkeying too much with builtin classes?

TIA
F.Valverde

Francisco-

It is intended behavior that package contents are not automatically imported or on the path. There is no intention to not allow users to write methods for builtin classes, though, if you override one of the builtin methods, some functionality may no longer work as intended.

I recommend you read the documentation for more information about how to work with packages.

–Loren

Hello Nausheen,

In my post I think I included the wrong code. My list is indeed a subclass of handle, and shows the performance characteristics from my last post:

>> list_compare
Elapsed time is 0.083423 seconds.
Elapsed time is 0.000395 seconds.

Any other ideas? Our application is severely bottlenecked by poor list performance. I wrote a detailed post below.

http://dacc.exaptic.com/2009/01/list-class-in-matlab-oo-overhead-pass-by-strategies/

Thanks,

- Daniel

Nausheen,

It’s also worth noting that when I use a value type for MyList I get extremely poor performance as you predicted.

>> list_compare
Elapsed time is 20.858983 seconds.
Elapsed time is 0.000622 seconds.

It’s very large compared with inheriting from handle, but inheriting from handle is still inexplicably slow as per my post above.

Thanks,

- Daniel

These postings are the author's and don't necessarily represent the opinions of MathWorks.