IN THIS CHAPTER
Defining Object Oriented Programming (OOP) principles
Considering MATLAB OOP differences
Creating a class
Using OOP in MATLAB
Objects are things that everyone uses every day. You grab a doorknob and turn it to open a door. Both the doorknob and the door are objects. Each has its own characteristics, and you wouldn’t confuse a doorknob for a door. The doorknob turns; the door opens. Each object has its own behaviors. In short, the use of objects is intuitive.
MATLAB supports the use of objects in the form of Object-Oriented Programming (OOP). OOP may sound complex, but like the doorknob and the door, using objects in MATLAB is actually quite intuitive, as described in the first part of the chapter.
Many programming languages support OOP, but they each have nuances. If you have used OOP with another language, you will find that working with OOP in MATLAB makes use of that knowledge. The second part of the chapter looks at differences between MATLAB OOP support and that provided in some common languages. You also discover how to use objects in MATLAB.
Creating your own MATLAB class, which is the code used to build an object, is the topic of the third part of the chapter. MATLAB tries to keep things simple. Consequently, the classes you create in MATLAB may not be as powerful as those you create in other languages, but the MATLAB classes are easy to understand, and they do everything you need to do with objects in MATLAB.
The fourth part of the chapter helps you use the class you designed to create objects and employ them to do something productive. This part of the chapter also helps you understand why certain class designs work better than others do. Creating truly useful classes means that you’ll ultimately do less work in MATLAB to produce some truly amazing results.
You don’t have to type the source code for this chapter manually. In fact, using the downloadable source is a lot easier. You can find the source for this chapter in the \MATLAB2\Chapter13 folder of the downloadable source. When using the downloadable source, you may not be able to work through some of the hands on examples because the example files will already exist on your system. In this case, you can create an alternative folder, Chapter13a, to hold the results of the hands on exercises. See the Introduction for details on how to obtain the downloadable source.
A Brief Overview of Object-Oriented Programming (OOP)
OOP is a formal method of defining how to interact with data in a safe manner using properties, which define the characteristics of the data, and methods, which define how to interact with the data. Take, for example, a doorknob made of brass. The brass is a property of the doorknob because it affects what you know about it; it’s the doorknob’s data. When turning a doorknob, you don’t change any of the doorknob’s characteristics; rather, you interact with the doorknob using the data defined for it. For example, some doorknobs may open only when turned clockwise, so the method of interacting with the doorknob is to turn it clockwise. Seeing objects in MATLAB helps you interact with abstract data in a more realistic manner. That’s what the following sections are about — helping you to see data in a new way.
Defining an object
An object in MATLAB is a real-world implementation of an underlying mathematical abstraction. This definition differs somewhat from the definition of an object in general-purpose languages. To put it into perspective, consider that you might create a complex algorithm in MATLAB that you want others to manipulate. Perhaps this algorithm calculates the amount of actual sunlight hitting the plants in a greenhouse based on the sunrise and sunset times, as well as the amount of cloud cover. The algorithm is abstract but produces a real-world result that someone can easily understand and use. The properties in this case would include:
· Sunrise time
· Sunset time
· Amount of cloud cover over time
These properties affect just the amount of sunshine, however. They don’t account for the needs of the plants. So, you might also need these properties:
· Sensitivity of plants to sunshine
· Amount of daily sunshine required by plants
Now you need some way of interacting with the data. The methods would include:
· Current amount of sunlight hitting the plants
· Adjustments needed for the greenhouse cover
Underlying these real-world concerns is a complex algorithm. The algorithm may be too abstract and complicated for most users to understand, but the terms used for the object make things simpler by relating them to the real world. Getting into the mindset that objects make abstractions real will help you create better classes, which in turn help more people use your truly amazing algorithms.
Considering how properties define an object
Your algorithm uses variables to define how it works — that is, what sort of output it produces. These variables, usually created as separate entities, are the actual data within the object. As a real-world example, an apple has properties like color, taste, and sweetness. Each of these properties is data about the apple. However, you don’t want anyone to modify the data in a way that will produce incorrect results from your algorithm or simply cause the entire application to crash. Properties allow you to manage how someone interacts with the data used by your algorithm. In fact, you should consider using properties to manage data in these ways:
· The data type of the input, such as an integer
· The range of the input, such as accepting only values greater than
· The value of the input based on the values of other data elements, such as accepting one value when another data element is true and other values when another data element is false
· The number of items required to perform analysis, such as a certain size vector
· Whether the property is read-only, such as when the property is an output value of the algorithm
· A default input value to use when the user doesn’t supply one
A class uses specific techniques to perform all these tasks. You see how to create a set of simple properties in the “Adding properties” section, later in this chapter. The important thing to remember is that properties always control how someone interacts with object data when created correctly.
Using methods to interact with an object
Methods are a kind of function. (See both Chapters 9 and 12 for more on functions.) The differences between functions and methods is that methods are part of an object and are designed to work with the data managed by that object. Because of these differences, methods work somewhat differently from functions, as you’ll see in the “Specifying methods” section, later in this chapter. For example, a special variable provides you with access to the underlying object. You often use methods to interact with data in these ways:
· Determine the value of a property
· Change the value of a property
· Perform tasks with object properties, such as creating a plot
· Verify that object properties will work together properly, such as by determining whether sensor inputs are within acceptable ranges
· Reset the object data to a known good state
· Define object behaviors, such as performing an action when inputs meet certain criteria
· Implement other object behaviors, such as raising an event (see the next section for details) when needed
There are many ways to use methods within an object to affect object data or use object data to perform specific tasks. However, methods always relate to the object in some way.
A special kind of method, called a constructor, creates an object based on the class you define. MATLAB classes can include one or more constructor methods as needed to help create the objects in a special way (such as by using arguments to automatically define property values). You always define a constructor for MATLAB classes, but MATLAB provides a default constructor when you create a new class. Creating an object from a class definition (which acts as a blueprint for the object) is called creating an instance of the class.
Listening to an object using events
An event is something that occurs because of a change. For example, when you turn the doorknob, the door opens. Likewise, having too much sun hitting the plants causes the greenhouse cover to close. When working with data, reaching a particular sensor threshold could cause the application to adjust the system associated with the sensor. In fact, events occur all the time in real life — we’re inundated with them and ignore many of them (or possibly respond automatically without thinking).
Just as in the real world, a MATLAB object can act as a source for events. It can also listen for events by registering itself as a listener. The events, even if no one is listening, are generated (triggered) as needed when certain things happen (such as reaching a threshold). There is a four-step process for events:
1. Define the event.
2. Add listeners for the event.
3. Trigger the event when the conditions are right.
4. React to the event as needed.
Unlike mandatory code, in which a function performs a task in MATLAB every time, events are far more flexible. An external piece of code must register as a listener to receive an event. So, not every piece of external code receives the event, and if there are no listeners, nothing receives the event at all. Even after receiving the event, a piece of code may choose not to act upon it depending on event attributes (values that indicate event conditions). Creating and using events is outside the scope of this chapter, but the list of articles at https://www.mathworks.com/help/matlab/events-sending-and-responding-to-messages.html offers helpful insights. The article at https://www.mathworks.com/help/matlab/matlab_oop/events-and-listeners-syntax-and-techniques.html provides you with some sample code examples.
Understanding the need for privacy
Properties provide access to data within an object. They rely on getters to obtain the data and setters to change the data. However, you might not always want properties to allow complete access. Perhaps you don’t want outsiders to see the property at all, which mean that it’s a nonpublic property. Protecting the data from harm is one of the tenets of OOP. However, sometimes it can be difficult to figure out just how much protection the data needs. The following list shows keywords used with properties to define a level of protection for properties. (You see the protection in action later in the chapter as part of creating a class, and then using it.)
· Constant: Allows someone to view the data but not modify it, even by internal methods. For example, the value of pi is something that you would allow an outsider to see, but you wouldn’t allow the outsider to modify because the value of pi never changes.
· GetAccess=private: Reduces property access to just the methods within the object so that it’s possible to create getters (methods that get the values) and setters (methods that set the values). Using getters and setters reduces risk of data corruption by allowing your code to validate any access or modification before it occurs.
· SetAccess=private: Makes a property read-only. Outside code can read the value but can’t modify it. Internal methods, however, can change the value of the property as needed.
· Dependent: Calculates the value of a property only when external code requests it using its dependent attribute. A dependent property has no value of its own. It doesn’t store a value, so you must calculate it each time.
Using getters and setters, disallowing free access to data, and protecting the methods used to manage data accomplish encapsulation, which is making the object a black box. The data is input and managed, but external code can’t determine how these processes take place. All that matters is that given a certain input, the caller can rely on a certain output. Using this approach leaves you free to change implementation details as needed.
Understanding OOP in MATLAB
When working in certain environments, you use objects all the time because that’s the preferred way of doing things. For example, when working with C++ or Java, you really do depend heavily on OOP. These languages support the OOP paradigm (pattern of solving problems) to the exclusion of every other paradigm.
MATLAB is more like Python because it supports multiple paradigms (see the article at https://blog.newrelic.com/engineering/python-programming-styles/ for a discussion about Python programming paradigms), only one of which is OOP. The following sections help you understand how OOP differs in MATLAB from other languages. You can easily skip the following sections if you aren’t coming from another language background and really don’t care to know OOP in any more detail than is needed to work with MATLAB.
Comparing MATLAB OOP to other languages
One of the overriding considerations of use of OOP in MATLAB is to make things simple. With this in mind, think about MATLAB as being less formal than many languages out there. For example, when you define a variable in a language such as C++ or Java, the variable is called a field, and you can access it directly without anything interfering with that access. In MATLAB, when you define a public property, you can also define a set and a get method for that property, which controls access to it. In this way, MATLAB makes it easier to ensure that your property is fully protected, even when you make the property public.
MATLAB classes deal with values most of the time, rather than references. When working with values, any change you make to the object only occurs in the current context. When working with references, changes occur to the underlying object and extend outside the current context. The one exception to this rule is if you create a class that derives from the handle class (see https://www.mathworks.com/help/matlab/ref/handle-class.html for details). In this case, you can use the object’s handle to work with it as a reference. If this whole issue of values versus references seems a little too difficult, the example code sections later in the chapter will help you.
There is no such thing as a static property in MATLAB. A static property is one that you access from the class, rather than from the object. You can use it to track class-specific variables, such as the number of existing objects in use. Because of how MATLAB works, using static properties would cause collisions between objects. You might actually find code examples purporting to provide a workaround for the static property limitation online, but the discussion at https://stackoverflow.com/questions/6450204/how-to-obtain-static-member-variables-in-matlab-classes makes it clear that using static properties is a recipe for disaster.
In some cases, it’s handy to create a copy constructor for your objects. A copy constructor is a special method that creates an object using a class as a blueprint and then fills the properties with values from another object. However, MATLAB doesn’t provide support for a copy constructor. One way to get around this problem is to define the original class as a handle class and then implement a copy method, as described at https://www.mathworks.com/help/matlab/matlab_oop/custom-copy-behavior.html. Using a copy method isn’t quite the same as a copy constructor because this approach requires multiple steps, but it should work for most needs.
OOP can become pretty complicated, and covering it in detail would require another book. Even covering the differences between MATLAB and languages like Java and C++ would consume a considerable amount of space. If you need additional details on how MATLAB compares to other languages, read the article at https://www.mathworks.com/help/matlab/matlab_oop/matlab-vs-other-oo-languages.html. This article provides significant detail, but the learning curve is also a little steep. It’s also helpful to review the code comparison at https://www.mathworks.com/matlabcentral/fileexchange/18972-comparison-of-c-java-python-ruby-and-matlab-oop-example for an understanding of how you’d implement a class in MATLAB when you have experience with other languages.
Uses of classes and objects in MATLAB
The essential reason to use classes and objects in MATLAB is to reduce complexity when your application gets large. You use OOP to break up code into smaller, more easily understood pieces. However, you must also consider that you have other options, such as using Live Script (see Chapter 11) to perform tasks in a different manner. In addition, you can combine methods to achieve specific results. For example, you could create all your plots as objects but then access them in a Live Script. With these various approaches in mind, here is how you generally use classes and objects in MATLAB:
· To hide the complexity of an underlying task
· To ensure that the focus remains on an outcome rather than the process for deriving that outcome
· When performing a task multiple times and a function or Live Function won’t reasonably achieve the desired result (such as processing a large number of input sensors)
· When working with other researchers, scientists, or professionals in other disciplines that may need a simple interface for complex tasks
· To keep data safe and uncorrupted
Performing tasks with objects in MATLAB
Later sections of the chapter show how to create and use classes from scratch. This section offers a brief overview of operations that you perform with objects. Of course, the most basic task is to create an object from a class definition:
object = MyClass;
In this case, object is an instance of MyClass. If you provide one or more constructors for MyClass, you can follow MyClass with parentheses and the required input values. Say that MyClass contains a property called Property1. You could then set this property in object, like this:
object.Property1 = 2;
Now Property1 contains the value 2, but only for the instance of MyClass called object. If you create another instance of MyClass, named object2, you could set Property1 to another value without affecting the value of Property1 in object. Each object you create is separate.
Unlike many other programming languages, MATLAB uses a different approach to working with methods. You specify the method, followed by the object to exercise the method in parentheses. For example, if an instance of MyClass named object has a method named DoAdd(), you use:
At some point, you need to interact with objects to determine their characteristics. Even if you created the class, you might forget about the presence of a particular property, method, or event. The following list provides functions that you can use to interact with objects:
· class(): Returns the class name of the object.
· enumeration(): Displays any class enumeration members and names. The class must actually contain an enumeration to allow use of this function.
· events(): Provides a list of event names defined by the class.
· help(): Displays help information as it would for any script or function.
· methods(): Provides a list of methods implemented by the class.
· methodsview(): Creates a separate window to list the methods implemented by the class.
· properties(): Provides a list of class property names. You can also obtain a list of property names by typing the object name and pressing Enter.
You may also need to compare two objects or an object and a class. The following functions help you perform these tasks.
· isa(): Determines whether an object is a member of a specific class.
· isequal(): Determines whether two objects are equal with regard to characteristics. Equality means that both objects are of the same class and size and their corresponding property values are equal.
· a == b (eq): Determines whether the handle variable a refers to the same object as handle variable b. In essence, it determines whether the two objects occupy the same memory — changes to a will affect b.
· isobject(): Outputs a logical true when the variable is a MATLAB object.
Creating a Basic MATLAB Class
It’s finally time to work through the class creation process. The following sections help you create a basic class that you can use for experimentation purposes.
Starting the class
The first thing you need to do is create the class file. The following steps get you started.
1. Choose New ⇒ Class in the File section of the Home tab.
You see a class definition (classdef) file like the one shown in Figure 13-1.
The class template supplies you with an outline of what your class might look like. You see a properties section and a methods section with a constructor and basic method. Each class you create will require some basic changes.
2. Change the classdef section so that it looks like this:
%MYCLASS provides an example of class creation.
% It shows how to define properties and methods.
These changes give your class a specific name and provide help information that you can obtain using the help() function.
FIGURE 13-1: MATLAB gets you started with a basic class outline.
3. Change the constructor method (the first one in the methods section) to look like this:
function obj = MyClass()
%MYCLASS Construct an instance of this class
% This is the default constructor.
obj.Property1 = 0;
This change ensures that you can create an instance of your class without supplying any arguments. It also sets Property1 to a default value. The pointer to this class instance appears in obj, which you use for other object-specific tasks within the class. In many languages, this kind of constructor is called a default constructor.
4. Change the method1() method to look like this:
function outputArg = method1(obj)
%METHOD1 Returns the Property1 value
% Just a starting point for methods.
outputArg = obj.Property1;
Normally, you replace method1() (and Property1, for that matter) with specific code. However, this section helps you get up and running with a very basic class quickly so that you get an idea of how things work.
5. Click Save.
You see the Select File for Save As dialog box. Notice that the dialog box provides a default filename that you should use. Like functions and scripts, this one uses an .m file extension.
6. Click Save.
MATLAB saves the file to disk for you.
You can now try the class you created. To start, type object = MyClass; in the Command Window and press Enter. This command creates an object of type MyClass for you to work with. To verify that the task was successful, type object and press Enter. You see this output:
MyClass with properties:
One of the things you should try is help. Type help('object') and press Enter; then click the Documentation for MyClass link. You see the window shown in Figure 13-2.
FIGURE 13-2: Class help screens give you detailed information about class characteristics.
Each of the items listed in the help window provides links for additional information. For example, if you click the method1 link, you see the help display shown in Figure 13-3. The interesting thing about help is that you can ask for specifics using a command as well. Type help('object.method1') and press Enter to see the details about method1() in the Command Window.
FIGURE 13-3: Drill down into the help display to get additional details.
To change the value of Property1, type object.Property1 = 5; and press Enter. You can verify the change by typing method1(object) and pressing Enter. MATLAB displays the following output:
Properties come in a number of forms in MATLAB, each with their specific attributes. If a property has no attributes, it’s a public property, and external code can access it freely. However, even with public properties, you can add get and set methods. The “Understanding the need for privacy” section, earlier in this chapter, describes the various nonpublic properties. Listing 13-1 shows these kinds of properties added to MyClass.
LISTING 13-1 Adding Properties to MyClass
pi = 3.141592653589793238;
If you add the properties as shown and then save the class, you can see how the various attributes affect property access. Type object and press Enter. You see output similar to this (Property1 might have a value of 5 instead):
MyClass with properties:
Notice that any changes you make to the class definition automatically affect existing objects. The public property, Property1, works just as it did before. Providing a custom setter will ensure that Property1 contains values in the correct range. For example, you might use a custom setter like this (placed in the methods section of the code):
function obj = set.Property1(obj, value)
obj.Property1 = value;
error('Input must be numeric!');
Notice that the set.Property1() function starts with set, followed by a period, followed by Property1. This is the pattern used for get and set functions. The function code checks to see whether value is numeric. If so, it gives Property1 a new value. Otherwise, it displays an error onscreen. You must return a new object when working with a setter, as shown by function obj in the preceding code. To try this new function, type object.Property1 = 2 and press Enter; the value of Property1 changes. However, when you type object.Property1 = 'Hello' and press Enter, you see an error message instead.
You can also see the constant property, pi, but MATLAB truncates its value in the output to match the current default format. The GetAccess=private attribute keeps you from seeing Property2. However, SetAccess=private lets you see Property3, which hasn’t been initialized, so you see an empty vector.
Type object.Property4 and press Enter. You see this error message:
In class 'MyClass', no get method is defined for
Dependent property 'Property4'. A Dependent property
needs a get method to access its value.
A property that has the Dependent attribute set stores no value, so requesting Property4 without defining a get method causes an error message. Adding the following function to the methods section of MyClass will fix the problem:
function value = get.Property4(obj)
value = class(obj.Property1);
The get.Property4() function code lacks any mention of Property4. This is because Property4 contains no value — it’s a calculated property. If you type object.Property4 and press Enter, you see the Property1 class, which is double. Likewise, if you type object and press Enter now, you also see the Property4 output.
MATLAB acts as if Property2 doesn’t exist because it has the GetAccess=private attribute set. If you type object.Property2 and press Enter, you see this error message.
No public property 'Property2' for class 'MyClass'.
Likewise, if you attempt to set the Property2 value by typing object.Property2 = 2 and pressing Enter, MATLAB acts as if you typed object by itself. In other words, Property2 has no outside access. To use Property2, you need to create a method that relies on it for a calculation or outputs it as a value.
You can’t set the value of Property3 because it has the SetAccess=private attribute. If you type object.Property3 = 2 and press Enter, you see this error message:
You cannot set the read-only property 'Property3' of MyClass.
You see a basic method defined in the “Starting the class” section of the chapter, along with a simple constructor. The preceding section, “Adding properties,” shows how to create methods associated with various kinds of properties. The MyClass example has a number of properties associated with it whose values can’t change directly while using the instantiated object. Consequently, it would be nice if you could create a constructor to set those properties. Fortunately, constructors can accept a variable number of inputs, as shown here (MATLAB classes can have only one constructor, so you need to delete or comment out the previous constructor before adding this one):
function obj = MyClass(Prop1, Prop2, Prop3)
%MYCLASS Construct an instance of this class
% This constructor will take a variable
% number of arguments. The arguments appear
% in order for Property1, Property2,
% and Property3.
if nargin >= 1
obj.Property1 = Prop1;
obj.Property1 = 0;
if nargin >= 2
obj.Property2 = Prop2;
obj.Property2 = 0;
if nargin == 3
obj.Property3 = Prop3;
obj.Property3 = 0;
Using this constructor will allow you to provide a variable number of values as input. For example, type obj = MyClass(1, 2, 3) and press Enter to define values for Property1, Property2, and Property3.
Methods can have attributes, just as properties can. You can see a list of method attributes at https://www.mathworks.com/help/matlab/matlab_oop/method-attributes.html. One of the more interesting method attributes is the Static attribute. You use this attribute to create methods that you can execute as part of the class, rather than as part of an instance. Here’s an example of a Static method:
function name = ShowName()
name = 'This is MyClass.';
Notice that you define a new methods section with the Static attribute, just as you do with property attributes. Defining the function ShowName() works like any other function, except that you don’t work with an object variable. In fact, you can’t access any of the property values, because they’re defined as part of an instance. To use this method, type MyClass.ShowName() and press Enter. You see the output shown here:
'This is MyClass.'