Matlab Oop
Matlab Oop
Matlab Oop
Product enhancement suggestions Bug reports Documentation error reports Order status, license renewals, passcodes Sales, pricing, and general information
508-647-7000 (Phone) 508-647-7001 (Fax) The MathWorks, Inc. 3 Apple Hill Drive Natick, MA 01760-2098
For contact information about worldwide offices, see the MathWorks Web site. Object-Oriented Programming COPYRIGHT 19842010 by The MathWorks, Inc.
The software described in this document is furnished under a license agreement. The software may be used or copied only under the terms of the license agreement. No part of this manual may be photocopied or reproduced in any form without prior written consent from The MathWorks, Inc. FEDERAL ACQUISITION: This provision applies to all acquisitions of the Program and Documentation by, for, or through the federal government of the United States. By accepting delivery of the Program or Documentation, the government hereby agrees that this software or documentation qualifies as commercial computer software or commercial computer software documentation as such terms are used or defined in FAR 12.212, DFARS Part 227.72, and DFARS 252.227-7014. Accordingly, the terms and conditions of this Agreement and only those rights specified in this Agreement, shall pertain to and govern the use, modification, reproduction, release, performance, display, and disclosure of the Program and Documentation by the federal government (or other entity acquiring for or through the federal government) and shall supersede any conflicting contractual terms or conditions. If this License fails to meet the governments needs or is inconsistent in any respect with federal procurement law, the government agrees to return the Program and Documentation, unused, to The MathWorks, Inc.
Trademarks
MATLAB and Simulink are registered trademarks of The MathWorks, Inc. See www.mathworks.com/trademarks for a list of additional trademarks. Other product or brand names may be trademarks or registered trademarks of their respective holders.
Patents
MathWorks products are protected by one or more U.S. patents. Please see www.mathworks.com/patents for more information.
Revision History
March 2008 October 2008 March 2009 September 2009 March 2010 September 2010
Online only Online only Online only Online only Online only Online only
New for MATLAB 7.6 (Release 2008a) Revised for MATLAB 7.7 (Release 2008b) Revised for MATLAB 7.8 (Release 2009a) Revised for MATLAB 7.9 (Release 2009b) Revised for MATLAB 7.10 (Release 2010a) Revised for Version 7.11 (Release 2010b)
Contents
Using Object-Oriented Design in MATLAB
1
Where to Begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Video Demo of MATLAB Classes . . . . . . . . . . . . . . . . . . . . . MATLAB Programmer Without Object-Oriented Programming Experience . . . . . . . . . . . . . . . . . . . . . . . . . MATLAB Programmer with Object-Oriented Programming Experience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Why Use Object-Oriented Design . . . . . . . . . . . . . . . . . . . . Approaches to Writing MATLAB Programs . . . . . . . . . . . . When Should You Start Creating Object-Oriented Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Class Diagrams Used in This Documentation . . . . . . . . . 1-2 1-2 1-2 1-2 1-4 1-4 1-8 1-17
2
MATLAB Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Classes in the MATLAB Language . . . . . . . . . . . . . . . . . . . Some Basic Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . Examples to Get Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . Learning Object-Oriented Programming . . . . . . . . . . . . . . . Detailed Information and Examples . . . . . . . . . . . . . . . . . Rapid Access to Information . . . . . . . . . . . . . . . . . . . . . . . . . Developing Classes Typical Workflow . . . . . . . . . . . . . Formulating a Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implementing the BankAccount Class . . . . . . . . . . . . . . . . Implementing the AccountManager Class . . . . . . . . . . . . . 2-2 2-2 2-4 2-6 2-7 2-8 2-8 2-11 2-11 2-13 2-15
Using the BankAccount Class . . . . . . . . . . . . . . . . . . . . . . . Using Objects to Write Data to a File . . . . . . . . . . . . . . . . Flexible Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Performing a Task with an Object . . . . . . . . . . . . . . . . . . . . Using Objects in Functions . . . . . . . . . . . . . . . . . . . . . . . . . . Example Representing Structured Data . . . . . . . . . . . Display Fully Commented Example Code . . . . . . . . . . . . . . Objects As Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . Structure of the Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining the TensileData Class . . . . . . . . . . . . . . . . . . . . . . Creating an Instance and Assigning Data . . . . . . . . . . . . . . Restricting Properties to Specific Values . . . . . . . . . . . . . . . Simplifying the Interface with a Constructor . . . . . . . . . . . Dependent Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Displaying TensileData Objects . . . . . . . . . . . . . . . . . . . . . . A Method to Plot Stress vs. Strain . . . . . . . . . . . . . . . . . . . . Example Implementing Linked Lists . . . . . . . . . . . . . . Displaying Fully Commented Example Code . . . . . . . . . . . Important Concepts Demonstrated . . . . . . . . . . . . . . . . . . . dlnode Class Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating Doubly Linked Lists . . . . . . . . . . . . . . . . . . . . . . . Why a Handle Class for Doubly Linked Lists? . . . . . . . . . . Defining the dlnode Class . . . . . . . . . . . . . . . . . . . . . . . . . . . Specializing the dlnode Class . . . . . . . . . . . . . . . . . . . . . . . . Example Class for Graphing Functions . . . . . . . . . . . . Display Fully Commented Example Code . . . . . . . . . . . . . . Class Definition Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the topo Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Behavior of the Handle Class . . . . . . . . . . . . . . . . . . . . . . . .
2-15 2-18 2-18 2-18 2-20 2-22 2-22 2-22 2-23 2-23 2-24 2-25 2-26 2-27 2-28 2-29 2-31 2-31 2-31 2-32 2-33 2-34 2-35 2-40 2-43 2-43 2-43 2-45 2-46
3
Class Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Options for Class Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2 3-2
vi
Contents
Grouping Classes with Package Folders . . . . . . . . . . . . . . . More Information on Class Folders . . . . . . . . . . . . . . . . . . . Class Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Class Building Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . More In Depth Information . . . . . . . . . . . . . . . . . . . . . . . . . The Classdef Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Specifying Attributes and Superclasses . . . . . . . . . . . . . . . . Assigning Class Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . Specifying Superclasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . Specifying Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What You Can Define . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How to Initialize Property Values . . . . . . . . . . . . . . . . . . . . Defining Default Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . Assigning Property Values from Within the Constructor . . Initializing Properties to Unique Values . . . . . . . . . . . . . . . Property Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Property Access Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . Referencing Object Properties Using Variables . . . . . . . . . Specifying Methods and Functions . . . . . . . . . . . . . . . . . . The Methods Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Method Calling Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Methods In Separate Files . . . . . . . . . . . . . . . . . . . . . . . . . . Defining Private Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . More Detailed Information On Methods . . . . . . . . . . . . . . . Defining Class-Related Functions . . . . . . . . . . . . . . . . . . . . Overloading Functions and Operators . . . . . . . . . . . . . . . . . Events and Listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Specifying Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Listening for Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Specifying Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Attribute Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Attribute Descriptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Specifying Attribute Values . . . . . . . . . . . . . . . . . . . . . . . . . Simpler Syntax for true/false Attributes . . . . . . . . . . . . . . .
3-3 3-4 3-5 3-5 3-6 3-6 3-7 3-7 3-7 3-8 3-8 3-8 3-9 3-9 3-10 3-10 3-11 3-11 3-13 3-13 3-14 3-14 3-16 3-16 3-16 3-17 3-19 3-19 3-19 3-21 3-21 3-21 3-22 3-22
vii
Calling Superclass Methods on Subclass Objects . . . . . Calling a Superclass Constructor . . . . . . . . . . . . . . . . . . . . . Calling Superclass Methods . . . . . . . . . . . . . . . . . . . . . . . . . A Class Code Listing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example of Class Definition Syntax . . . . . . . . . . . . . . . . . . Understanding Code Analyzer Warnings . . . . . . . . . . . . . Syntax Warnings and Property Names . . . . . . . . . . . . . . . . Warnings Caused by Variable/Property Name Conflicts . . Exception to Variable/Property Name Rule . . . . . . . . . . . . . Functions Used with Objects . . . . . . . . . . . . . . . . . . . . . . . Functions to Query Class Members . . . . . . . . . . . . . . . . . . . Functions to Test Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the Editor and Debugger with Classes . . . . . . . . . Referring to Class Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modifying and Reloading Classes . . . . . . . . . . . . . . . . . . . Ensuring MATLAB Uses Your Changes . . . . . . . . . . . . . . . Compatibility with Previous Versions . . . . . . . . . . . . . . . New Class-Definition Syntax Introduced with MATLAB Software Version 7.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Changes to Class Constructors . . . . . . . . . . . . . . . . . . . . . . . New Features Introduced with Version 7.6 . . . . . . . . . . . . . Examples of Old and New . . . . . . . . . . . . . . . . . . . . . . . . . . . MATLAB Vs. Other OO Languages . . . . . . . . . . . . . . . . . . Some Differences from C++ and Sun Java Code . . . . . . . . . Modifying Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Common Object-Oriented Techniques . . . . . . . . . . . . . . . . .
3-24 3-24 3-25 3-27 3-27 3-29 3-29 3-29 3-30 3-32 3-32 3-32 3-33 3-33 3-34 3-34 3-37 3-37 3-38 3-39 3-39 3-41 3-41 3-42 3-47
viii
Contents
4
Class Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MATLAB User-Defined Classes . . . . . . . . . . . . . . . . . . . . . . Defining Classes Syntax . . . . . . . . . . . . . . . . . . . . . . . . . classdef Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Class Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table of Class Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . Specifying Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Expressions in Class Definitions . . . . . . . . . . . . . . Basic Knowledge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Where Can You Use Expressions . . . . . . . . . . . . . . . . . . . . . How MATLAB Evaluates Expressions . . . . . . . . . . . . . . . . Organizing Classes in Folders . . . . . . . . . . . . . . . . . . . . . . Options for Class Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . @-Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Path Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Access to Functions Defined in Private Folders . . . . . . . . . Class Precedence and MATLAB Path . . . . . . . . . . . . . . . . . Specifying Class Precedence . . . . . . . . . . . . . . . . . . . . . . . . InferiorClasses Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . Scoping Classes with Packages . . . . . . . . . . . . . . . . . . . . . Package Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Referencing Package Members Within Packages . . . . . . . . Referencing Package Members from Outside the Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Packages and the MATLAB Path . . . . . . . . . . . . . . . . . . . . . Importing Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Related Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Syntax for Importing Classes . . . . . . . . . . . . . . . . . . . . . . . . 4-2 4-2 4-4 4-4 4-5 4-5 4-6 4-7 4-7 4-7 4-9 4-13 4-13 4-13 4-14 4-14 4-14 4-17 4-17 4-19 4-19 4-20 4-20 4-22 4-24 4-24 4-24
ix
5
Comparing Handle and Value Classes . . . . . . . . . . . . . . . Basic Difference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Why Select Handle or Value . . . . . . . . . . . . . . . . . . . . . . . . . Behavior of MATLAB Built-In Classes . . . . . . . . . . . . . . . . Behavior of User-Defined Classes . . . . . . . . . . . . . . . . . . . . Which Kind of Class to Use . . . . . . . . . . . . . . . . . . . . . . . . . Examples of Value and Handle Classes . . . . . . . . . . . . . . . . When to Use Handle Classes . . . . . . . . . . . . . . . . . . . . . . . . When to Use Value Classes . . . . . . . . . . . . . . . . . . . . . . . . . The Handle Superclass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Building on the Handle Class . . . . . . . . . . . . . . . . . . . . . . . . Handle Class Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Relational Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Testing Handle Validity . . . . . . . . . . . . . . . . . . . . . . . . . . . . Handle Class Delete Methods . . . . . . . . . . . . . . . . . . . . . . . Finding Handle Objects and Properties . . . . . . . . . . . . . . Finding Handle Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . Finding Handle Object Properties . . . . . . . . . . . . . . . . . . . . Implementing a Set/Get Interface for Properties . . . . . The Standard Set/Get Interface . . . . . . . . . . . . . . . . . . . . . . Property Get Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Property Set Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Subclassing hgsetget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Controlling the Number of Instances . . . . . . . . . . . . . . . . Limiting Instances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2 5-2 5-2 5-3 5-4 5-9 5-9 5-9 5-10 5-11 5-11 5-12 5-12 5-13 5-15 5-19 5-19 5-19 5-21 5-21 5-21 5-22 5-22 5-25 5-25
Contents
6
How to Use Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What Are Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Types of Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Property Definition Block . . . . . . . . . . . . . . . . . . . . . . . . . . . Accessing Property Values . . . . . . . . . . . . . . . . . . . . . . . . . . Inheritance of Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . Specifying Property Attributes . . . . . . . . . . . . . . . . . . . . . . . Property Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table of Property Attributes . . . . . . . . . . . . . . . . . . . . . . . . . Property Set and Get Access Methods . . . . . . . . . . . . . . . Property Access Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . Property Set Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Property Get Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Set and Get Method Execution and Property Events . . . . . Access Methods and Subscripted Reference and Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Performing Additional Steps with Property Access Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dynamic Properties Adding Properties to an Instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What Are Dynamic Properties . . . . . . . . . . . . . . . . . . . . . . . Defining Dynamic Properties . . . . . . . . . . . . . . . . . . . . . . . . Responding to Dynamic-Property Events . . . . . . . . . . . . . . Defining Property Access Methods for Dynamic Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dynamic Properties and ConstructOnLoad . . . . . . . . . . . . . 6-2 6-2 6-3 6-5 6-5 6-6 6-6 6-7 6-8 6-8 6-12 6-12 6-14 6-16 6-18 6-19 6-20
xi
7
Class Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What Are Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Method Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table of Method Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . Ordinary Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Determining Which Method Is Invoked . . . . . . . . . . . . . . . . Specifying Precedence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Controlling Access to Methods . . . . . . . . . . . . . . . . . . . . . . . Invoking Superclass Methods in Subclass Methods . . . . . . Invoking Built-In Methods . . . . . . . . . . . . . . . . . . . . . . . . . . Class Constructor Methods . . . . . . . . . . . . . . . . . . . . . . . . . Rules for Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Related Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Examples of Class Constructors . . . . . . . . . . . . . . . . . . . . . . Initializing the Object Within a Constructor . . . . . . . . . . . . Constructing Subclasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . Errors During Class Construction . . . . . . . . . . . . . . . . . . . . Basic Structure of Constructor Methods . . . . . . . . . . . . . . . Static Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Why Define Static Methods . . . . . . . . . . . . . . . . . . . . . . . . . Calling Static Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overloading Functions for Your Class . . . . . . . . . . . . . . . Overloading MATLAB Functions . . . . . . . . . . . . . . . . . . . . . Rules for Naming to Avoid Conflicts . . . . . . . . . . . . . . . . . . Object Precedence in Expressions Using Operators . . . Specifying Precedence of User-Defined Classes . . . . . . . . . Class Methods for Graphics Callbacks . . . . . . . . . . . . . . . Callback Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . General Syntax for Callbacks . . . . . . . . . . . . . . . . . . . . . . . . 7-2 7-2 7-4 7-4 7-6 7-6 7-8 7-12 7-12 7-13 7-14 7-15 7-15 7-16 7-16 7-17 7-19 7-21 7-22 7-24 7-24 7-25 7-26 7-26 7-27 7-29 7-29 7-31 7-31 7-31
xii
Contents
Object Scope and Anonymous Functions . . . . . . . . . . . . . . . Example Class Method as a Slider Callback . . . . . . . . .
7-32 7-33
Object Arrays
8
Information About Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . Basic Knowledge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating Object Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Building Arrays in the Constructor . . . . . . . . . . . . . . . . . . . Creating Empty Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arrays of Handle Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . Referencing Property Values in Object Arrays . . . . . . . . . . Object Arrays with Dynamic Properties . . . . . . . . . . . . . . . Concatenating Objects of Different Classes . . . . . . . . . . Basic Knowledge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MATLAB Concatenation Rules . . . . . . . . . . . . . . . . . . . . . . Concatenating Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Converting to the Dominant Class . . . . . . . . . . . . . . . . . . . . Implementing Converter Methods . . . . . . . . . . . . . . . . . . . . 8-2 8-2 8-3 8-3 8-6 8-7 8-10 8-10 8-13 8-13 8-13 8-13 8-14 8-17
9
Learning to Use Events and Listeners . . . . . . . . . . . . . . . What You Can Do With Events and Listeners . . . . . . . . . . Some Basic Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simple Event Listener Example . . . . . . . . . . . . . . . . . . . . . Responding to a Button Click . . . . . . . . . . . . . . . . . . . . . . . . Events and Listeners Concepts . . . . . . . . . . . . . . . . . . . The Event Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Default Event Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-2 9-2 9-2 9-3 9-6 9-9 9-9 9-11
xiii
Events Only in Handle Classes . . . . . . . . . . . . . . . . . . . . . . Property-Set and Query Events . . . . . . . . . . . . . . . . . . . . . . Listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Event Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table of Event Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining Events and Listeners Syntax and Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Naming Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Triggering Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Listening to Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining Event-Specific Data . . . . . . . . . . . . . . . . . . . . . . . . Ways to Create Listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining Listener Callback Functions . . . . . . . . . . . . . . . . . Listening for Changes to Property Values . . . . . . . . . . . . Creating Property Listeners . . . . . . . . . . . . . . . . . . . . . . . . . Example Property Event and Listener Classes . . . . . . . . . . Aborting Set When Value Does Not Change . . . . . . . . . . . . Example Using Events to Update Graphs . . . . . . . . . . Example Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Access Fully Commented Example Code . . . . . . . . . . . . . . . Techniques Demonstrated in This Example . . . . . . . . . . . . Summary of fcneval Class . . . . . . . . . . . . . . . . . . . . . . . . . . Summary of fcnview Class . . . . . . . . . . . . . . . . . . . . . . . . . . Methods Inherited from Handle Class . . . . . . . . . . . . . . . . . Using the fcneval and fcnview Classes . . . . . . . . . . . . . . . . Implementing the UpdateGraph Event and Listener . . . . . Implementing the PostSet Property Event and Listener . . Enabling and Disabling the Listeners . . . . . . . . . . . . . . . . .
9-15 9-15 9-15 9-16 9-18 9-19 9-21 9-23 9-23 9-25 9-27 9-30 9-30 9-31 9-32 9-32 9-33 9-35 9-35 9-38 9-43 9-46
10
Hierarchies of Classes Concepts . . . . . . . . . . . . . . . . . . Classification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Developing the Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 10-2 10-3
xiv
Contents
Designing Class Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . Super and Subclass Behavior . . . . . . . . . . . . . . . . . . . . . . . . Implementation and Interface Inheritance . . . . . . . . . . . . .
Creating Subclasses Syntax and Techniques . . . . . . . 10-7 Defining a Subclass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-7 Referencing Superclasses from Subclasses . . . . . . . . . . . . . 10-7 Constructor Arguments and Object Initialization . . . . . . . . 10-9 Call Only Direct Superclass from Constructor . . . . . . . . . . 10-10 Sequence of Constructor Calls in a Class Hierarchy . . . . . 10-11 Using a Subclass to Create an Alias for an Existing Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-12 Modifying Superclass Methods and Properties . . . . . . . Modifying Superclass Methods . . . . . . . . . . . . . . . . . . . . . . . Modifying Superclass Properties . . . . . . . . . . . . . . . . . . . . . Private Local Property Takes Precedence in Method . . . . . 10-13 10-13 10-15 10-15
Subclassing Multiple Classes . . . . . . . . . . . . . . . . . . . . . . . 10-17 Class Member Compatibility . . . . . . . . . . . . . . . . . . . . . . . . 10-17 Subclassing MATLAB Built-In Classes . . . . . . . . . . . . . . . MATLAB Built-In Classes . . . . . . . . . . . . . . . . . . . . . . . . . . Why Subclass Built-In Classes . . . . . . . . . . . . . . . . . . . . . . . Behavior of Built-In Functions with Subclass Objects . . . . Example A Class to Manage uint8 Data . . . . . . . . . . . . . Example Adding Properties to a Built-In Subclass . . . . Understanding size and numel . . . . . . . . . . . . . . . . . . . . . . Example A Class to Represent Hardware . . . . . . . . . . . . Abstract Classes and Interfaces . . . . . . . . . . . . . . . . . . . . . Abstract Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Interfaces and Abstract Classes . . . . . . . . . . . . . . . . . . . . . . Example Interface for Classes Implementing Graphs . . 10-19 10-19 10-19 10-21 10-28 10-35 10-41 10-46 10-50 10-50 10-51 10-52
xv
11
The Save and Load Process . . . . . . . . . . . . . . . . . . . . . . . . . The Default Save and Load Process . . . . . . . . . . . . . . . . . . . When to Modify Object Saving and Loading . . . . . . . . . . . . Modifying the Save and Load Process . . . . . . . . . . . . . . . Class saveobj and loadobj Methods . . . . . . . . . . . . . . . . . . . Processing Objects During Load . . . . . . . . . . . . . . . . . . . . . . Save and Load Applications . . . . . . . . . . . . . . . . . . . . . . . . . Example Maintaining Class Compatibility . . . . . . . . . Versions of a Phone Book Application Program . . . . . . . . . Passing Arguments to Constructors During Load . . . . . Calling Constructors When Loading Objects . . . . . . . . . . . . Code for This Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-2 11-2 11-4 11-6 11-6 11-7 11-7 11-9 11-9 11-14 11-14 11-14 11-14
Saving and Loading Objects from Class Hierarchies . . 11-17 Saving and Loading Subclass Objects . . . . . . . . . . . . . . . . . 11-17 Saving and Loading Dynamic Properties . . . . . . . . . . . . 11-20 Reconstructing Objects That Have Dynamic Properties . . 11-20 Tips for Saving and Loading . . . . . . . . . . . . . . . . . . . . . . . . Using Default Property Values to Reduce Storage . . . . . . . Avoiding Property Initialization Order Dependency . . . . . When to Use Transient Properties . . . . . . . . . . . . . . . . . . . . Calling Constructor When Loading . . . . . . . . . . . . . . . . . . . 11-22 11-22 11-23 11-25 11-25
Enumerations
12
Defining Named Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kinds of Predefined Names . . . . . . . . . . . . . . . . . . . . . . . . . 12-2 12-2
xvi
Contents
Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Basic Knowledge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Enumeration Classes . . . . . . . . . . . . . . . . . . . . . . . . . Defining Methods in Enumeration Classes . . . . . . . . . . . . . Defining Properties in Enumeration Classes . . . . . . . . . . . Array Expansion Operations . . . . . . . . . . . . . . . . . . . . . . . . Constructor Calling Sequence . . . . . . . . . . . . . . . . . . . . . . . Restrictions Applied to Enumeration Classes . . . . . . . . . . . Techniques for Defining Enumerations . . . . . . . . . . . . . . . . Enumerations Derived from Built-In Classes . . . . . . . . . Basic Knowledge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Why Derive Enumeration Class from Built-In Classes . . . Aliasing Enumeration Names . . . . . . . . . . . . . . . . . . . . . . . Superclass Constructor Returns Underlying Value . . . . . . Default Converter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mutable (Handle) vs. Immutable (Value) Enumeration Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Basic Knowledge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Selecting Handle- or Value-Based Enumerations . . . . . . . . Value-Based Enumeration Classes . . . . . . . . . . . . . . . . . . . Handle-Based Enumeration Classes . . . . . . . . . . . . . . . . . . Example Using Enumerations to Represent a State . . . .
12-4 12-4 12-5 12-8 12-9 12-10 12-11 12-13 12-13 12-15 12-15 12-15 12-17 12-18 12-19
Enumerations That Encapsulate Data . . . . . . . . . . . . . . . 12-28 Store Data in Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-28 Saving and Loading Enumerations . . . . . . . . . . . . . . . . . . Basic Knowledge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Built-In and Value-Based Enumeration Classes . . . . . . . . Simple and Handle-Based Enumeration Classes . . . . . . . . What Causes Loading as a Struct Instead of an Object . . . 12-32 12-32 12-32 12-32 12-33
Constant Properties
13
Defining Named Constants . . . . . . . . . . . . . . . . . . . . . . . . . Defining Named Constants . . . . . . . . . . . . . . . . . . . . . . . . . 13-2 13-2
xvii
...................
13-4
14
Working with Meta-Classes . . . . . . . . . . . . . . . . . . . . . . . . . What Are Meta-Classes? . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Meta-Classes to Inspect Classes and Objects . . . Inspecting a Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Meta-Class EnumeratedValues Property . . . . . . . . . . . . . . Finding Objects Having Specific Settings . . . . . . . . . . . . Finding Handle Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . Perusing Meta-Classes with findobj . . . . . . . . . . . . . . . . . . . 14-2 14-2 14-4 14-4 14-6 14-7 14-7 14-8
Getting Information About Properties . . . . . . . . . . . . . . . 14-10 Information Contained in the meta.property object . . . . . . 14-10 Example Finding Properties with Specific Attributes . . 14-14 Getting Property Default Values . . . . . . . . . . . . . . . . . . . . 14-17 Property Default Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-17
15
Methods That Modify Default Behavior . . . . . . . . . . . . . . How to Modify Behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . Which Methods Control Which Behaviors . . . . . . . . . . . . . . Overloading and Overriding Functions and Methods . . . . . When to Overload MATLAB Functions . . . . . . . . . . . . . . . . Caution When Overloading MATLAB Functions . . . . . . . . 15-2 15-2 15-2 15-4 15-5 15-6
xviii
Contents
Redefining Concatenation for Your Class . . . . . . . . . . . . Default Concatenation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Displaying Objects in the Command Window . . . . . . . . . Default Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Converting Objects to Another Class . . . . . . . . . . . . . . . . 15-11 Why Implement a Converter . . . . . . . . . . . . . . . . . . . . . . . . 15-11 Indexed Reference and Assignment . . . . . . . . . . . . . . . . . Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Default Indexed Reference and Assignment . . . . . . . . . . . . What You Can Modify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . subsref and subsasgn Within Class Methods Built-In Called . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Understanding Indexed Reference . . . . . . . . . . . . . . . . . . . . Avoid Overriding Access Attributes . . . . . . . . . . . . . . . . . . . Understanding Indexed Assignment . . . . . . . . . . . . . . . . . . A Class with Modified Indexing . . . . . . . . . . . . . . . . . . . . . . Defining end Indexing for an Object . . . . . . . . . . . . . . . . . . Using Objects as Indices . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-13 15-13 15-13 15-15 15-16 15-18 15-21 15-23 15-26 15-31 15-32
Implementing Operators for Your Class . . . . . . . . . . . . . 15-35 Overloading Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-35 MATLAB Operators and Associated Functions . . . . . . . . . 15-36
16
Example A Polynomial Class . . . . . . . . . . . . . . . . . . . . . 16-2 Adding a Polynomial Object to the MATLAB Language . . 16-2 Displaying the Class Files . . . . . . . . . . . . . . . . . . . . . . . . . . 16-2 Summary of the DocPolynom Class . . . . . . . . . . . . . . . . . . . 16-3 The DocPolynom Constructor Method . . . . . . . . . . . . . . . . . 16-5 Removing Irrelevant Coefficients . . . . . . . . . . . . . . . . . . . . . 16-6 Converting DocPolynom Objects to Other Types . . . . . . . . 16-7 The DocPolynom disp Method . . . . . . . . . . . . . . . . . . . . . . . 16-10 The DocPolynom subsref Method . . . . . . . . . . . . . . . . . . . . . 16-11 Defining Arithmetic Operators for DocPolynom . . . . . . . . . 16-14
xix
17
Example A Simple Class Hierarchy . . . . . . . . . . . . . . . Shared and Specialized Properties . . . . . . . . . . . . . . . . . . . . Designing a Class for Financial Assets . . . . . . . . . . . . . . . . Displaying the Class Files . . . . . . . . . . . . . . . . . . . . . . . . . . Summary of the DocAsset Class . . . . . . . . . . . . . . . . . . . . . . The DocAsset Constructor Method . . . . . . . . . . . . . . . . . . . . The DocAsset Display Method . . . . . . . . . . . . . . . . . . . . . . . Designing a Class for Stock Assets . . . . . . . . . . . . . . . . . . . Displaying the Class Files . . . . . . . . . . . . . . . . . . . . . . . . . . Summary of the DocStock Class . . . . . . . . . . . . . . . . . . . . . Designing a Class for Bond Assets . . . . . . . . . . . . . . . . . . . . Displaying the Class Files . . . . . . . . . . . . . . . . . . . . . . . . . . Summary of the DocBond Class . . . . . . . . . . . . . . . . . . . . . . Designing a Class for Savings Assets . . . . . . . . . . . . . . . . . Displaying the Class Files . . . . . . . . . . . . . . . . . . . . . . . . . . Summary of the DocSavings Class . . . . . . . . . . . . . . . . . . . . Example Containing Assets in a Portfolio . . . . . . . . . . Kinds of Containment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Designing the DocPortfolio Class . . . . . . . . . . . . . . . . . . . . . Displaying the Class Files . . . . . . . . . . . . . . . . . . . . . . . . . . Summary of the DocPortfolio Class . . . . . . . . . . . . . . . . . . . The DocPortfolio Constructor Method . . . . . . . . . . . . . . . . . The DocPortfolio disp Method . . . . . . . . . . . . . . . . . . . . . . . The DocPortfolio pie3 Method . . . . . . . . . . . . . . . . . . . . . . . Visualizing a Portfolio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-2 17-2 17-3 17-4 17-4 17-5 17-6 17-7 17-7 17-7 17-10 17-10 17-11 17-15 17-15 17-15 17-19 17-19 17-19 17-19 17-20 17-22 17-23 17-23 17-25
Index
xx
Contents
1
Using Object-Oriented Design in MATLAB
Where to Begin on page 1-2 Why Use Object-Oriented Design on page 1-4 Class Diagrams Used in This Documentation on page 1-17
Where to Begin
In this section... Video Demo of MATLAB Classes on page 1-2 MATLAB Programmer Without Object-Oriented Programming Experience on page 1-2 MATLAB Programmer with Object-Oriented Programming Experience on page 1-2
1-2
Where to Begin
Compatibility with Previous Versions on page 3-37 MATLAB Vs. Other OO Languages on page 3-41
1-3
1-4
After performing this analysis, you define classes that describe the objects your application uses.
In this code, ME is an object of the MException class, which is returned by the catch statement to the functions workspace. Displaying the value of the objects message property returns information about the error (the surf
1-5
function requires input arguments). However, this is not all the information available in the MException object. You can list the public properties of an object with the properties function:
properties(ME) Properties for class MException: identifier message cause stack
shows that the value of the message property is an array of class char (a text string). The stack property contains a MATLAB struct:
ME.stack ans = file: 'U:\bat\A\perfect\matlab\toolbox\matlab\graph3d\surf.m' name: 'surf' line: 50
You can simply treat the property reference, ME.stack as a structure and reference its fields:
ME.stack.file ans = D:\myMATLAB\matlab\toolbox\matlab\graph3d\surf.m
The file field of the struct contained in the stack property is a character array:
1-6
Object properties can contain any class of value and can even determine their value dynamically. This provides more flexibility than a structure and is easier to investigate than a cell array, which lacks fieldnames and requires indexing into various cells using array dimensions.
Static methods:
1-7
last
You can use these methods like any other MATLAB statement when there is an MException object in the workspace. For example:
ME.getReport ans = ??? Error using ==> surf at 50 Not enough input arguments.
Objects often have methods that overload (redefined for the particular object) MATLAB functions (e.g., isequal, fieldnames, etc.). This enables you to use objects just like other values. For example, MException objects have an isequal method. This method enables you to compare these objects in the same way you would compare variables containing doubles. If ME and ME2 are MException objects, you can compare them with this statement:
isequal(ME,ME2)
However, what really happens in this case is MATLAB calls the MException isequal method because you have passed MException objects to isequal. Similarly, the eq method enables you to use the == operator with MException objects:
ME == ME2
Of course, objects should support only those methods that make sense. For example, it would probably not make sense to multiply MException objects so the MException class does not implement methods to do so.
1-8
As functions become too large, you might break them into smaller functions and pass data from one to the other. However, as the number of functions becomes large, designing and managing the data passed to functions becomes difficult and error prone. At this point, you should consider moving your MATLAB programming tasks to object-oriented designs.
1-9
Add Only What Is Necessary. It is likely that these institutions engage in many activities that are not of interest to your application. During the design phase, you need to determine what operations and data an object needs to contain based on your problem definition. Managing Data. Objects encapsulate the model of what the object represents. If the object represents a kind of lending institution, all the behaviors of lending institutions that are necessary for your application are contained by this object. This approach simplifies the management of data that is necessary in a typical procedural program.
1-10
Reducing Redundancy
As the complexity of your program increases, the benefits of an object-oriented design become more apparent. For example, suppose you need to implement the following procedure as part of your application:
1 Check inputs 2 Perform computation on the first input argument 3 Transform the result of step 2 based on the second input argument 4 Check validity of outputs and return values
This simple procedure is easily implemented as an ordinary function. But now suppose you need to use this procedure again somewhere in your application, except that step 2 must perform a different computation. You could simply copy and paste the first implementation, and then rewrite step 2. Or you could create a function that accepted an option indicating which computation to make, and so on. However, these options lead to more and more complicated code. An object-oriented design could result in a simpler solution by factoring out the common code into what is called a base class. The base class would define the algorithm used and implement whatever is common to all cases that use this code. Step 2 could be defined syntactically, but not implemented, leaving the specialized implementation to the classes that you then derive from this base class.
Step 1 function checkInputs() % actual implementation end Step 2 function results = computeOnFirstArg() % specify syntax only end Step 3 function transformResults()
1-11
% actual implementation end Step 4 function out = checkOutputs() % actual implementation end
The code in the base class is not copied or modified, it is inherited by the various classes you derive from the base class. This reduces the amount of code to be tested, and isolates your program from changes to the basic procedure.
1-12
All of the classes derived from the interface class can create a method called getReport without any name conflicts because it is the class of the object that determines which getReport is called.
Reducing Complexity
Objects reduce complexity by reducing what you need to know to use a component or part of a system. This happens in a couple of ways: Implementation details are hidden behind the interfaces defined by objects. Rules controlling how objects interact are enforced by object design and, therefore, not left to object users to enforce. To illustrate these advantages, consider the implementation of a data structure called a doubly linked list.
To add a new node to the list, the following steps must occur. First disconnect the nodes:
1 Unlink n2.Prev from n1 2 Unlink n2.Next from n3 3 Unlink n3.Prev from n2 4 Unlink n1.Next from n2
1-13
1-14
The objects enforce the rules for how the nodes interact by implementing methods to carry out these operations. A single addNode method would perform all the steps listed above. This removes the responsibility for enforcing constraints from the applications that use the objects. It also means the application is less likely to generate errors in its own implementation of the process. This approach can reduce the complexity of your application code, provide greater consistency across applications, and reduce testing and maintenance requirements.
Fostering Modularity
As you decompose a system into objects (car > engine > fuel system > oxygen sensor), you form modules around natural boundaries. These objects provide interfaces by which they interact with other modules (which might be other objects or functions). Often the data and operations behind the interface are hidden from other modules to segregate implementation from interface. Classes provide three levels of control over code modularity: Public Any code can access this particular property or call this method. Protected Only the objects own methods and those of the objects whose class has been derived from this objects class can access this property or call this method. Private Only the objects own methods can access this property or call this method.
1-15
dialog windows, and then deriving the specific dialog classes from this base class, you can: Reuse code that is common to all dialog window implementations Reduce code testing effort due to common code Provide a common interface to dialog developers Enforce a consistent look and feel Apply global changes to all dialog windows more easily
Learning More
See MATLAB Classes on page 2-2 to learn more about writing object-oriented MATLAB programs.
1-16
1-17
Concept
Graphical representation
Example BankAccount
Object
Asset
is_a Stock
FileID
Tire
1-18
2
MATLAB Classes Overview
MATLAB Classes on page 2-2 Detailed Information and Examples on page 2-8 Developing Classes Typical Workflow on page 2-11 Using Objects to Write Data to a File on page 2-18 Example Representing Structured Data on page 2-22 Example Implementing Linked Lists on page 2-31 Example Class for Graphing Functions on page 2-43
MATLAB Classes
In this section... Classes in the MATLAB Language on page 2-2 Some Basic Relationships on page 2-4 Examples to Get Started on page 2-6 Learning Object-Oriented Programming on page 2-7
Bytes 8 22
Basic commands like whos display the class of each value in the workspace. This information helps MATLAB users recognize that some values are characters and display as text while other values might be double, single, or other types of numbers. Some variables can contain different classes of values like cells.
User-Defined Classes
You can create your own MATLAB classes. For example, you could define a class to represent polynomials. This class could define the operations typically associated with MATLAB classes, like addition, subtraction, indexing, displaying in the command window, and so on. However, these operations would need to perform the equivalent of polynomial addition, polynomial subtraction, and so on. For example, when you add two polynomial objects:
p1 + p2
2-2
MATLAB Classes
the plus operation would know how to add polynomial objects because the polynomial class defines this operation. When you define a class, you overload special MATLAB functions (plus.m for the addition operator) that are called by the MATLAB runtime when those operations are applied to an object of your class. See Example A Polynomial Class on page 16-2 for an example that creates just such a class.
2-3
These are general descriptions of these components and concepts. This documentation describes all of these components in detail.
Classes
A class is a definition that specifies certain characteristics that all instances of the class share. These characteristics are determined by the properties, methods, and events that define the class and the values of attributes that modify the behavior of each of these class components. Class definitions describe how objects of the class are created and destroyed, what data the objects contain, and how you can manipulate this data.
Class Hierarchies
It sometimes makes sense to define a new class in terms of existing classes. This enables you to reuse the designs and techniques in a new class that represents a similar entity. You accomplish this reuse by creating a subclass. A subclass defines objects that are a subset of those defined by the superclass. A subclass is more specific than its superclass and might add new properties, methods, and events to those inherited from the superclass. Mathematical sets can help illustrate the relationships among classes. In the following diagram, the set of Positive Integers is a subset of the set of Integers and a subset of Positive numbers. All three sets are subsets of Real numbers, which is a subset of All Numbers. The definition of Positive Integers requires the additional specification that members of the set be greater than zero. Positive Integers combine the definitions from both Integers and Positives. The resulting subset is more specific, and therefore more narrowly defined, than the supersets, but still shares all the characteristics that define the supersets.
2-4
MATLAB Classes
The is a relationship is a good way to determine if it is appropriate to define a particular subset in terms of existing supersets. For example, each of the following statements makes senses: A Positive Integer is an Integer A Positive Integer is a Positive number If the is a relationship holds, then it is likely you can define a new a class from a class or classes that represent some more general case.
Reusing Solutions
Classes are usually organized into taxonomies to foster code reuse. For example, if you define a class to implement an interface to the serial port of a computer, it would probably be very similar to a class designed to implement an interface to the parallel port. To reuse code, you could define a superclass that contains everything that is common to the two types of ports, and then
2-5
derive subclasses from the superclass in which you implement only what is unique to each specific port. Then the subclasses would inherit all of the common functionality from the superclass.
Objects
A class is like a template for the creation of a specific instance of the class. This instance or object contains actual data for a particular entity that is represented by the class. For example, an instance of a bank account class is an object that represents a specific bank account, with an actual account number and an actual balance. This object has built into it the ability to perform operations defined by the class, such as making deposits to and withdrawals from the account balance. Objects are not just passive data containers. Objects actively manage the data contained by allowing only certain operations to be performed, by hiding data that does not need to be public, and by preventing external clients from misusing data by performing operations for which the object was not designed. Objects even control what happens when they are destroyed.
Encapsulating Information
An important aspect of objects is that you can write software that accesses the information stored in the object via its properties and methods without knowing anything about how that information is stored, or even whether it is stored or calculated when queried. The object isolates code that accesses the object from the internal implementation of methods and properties. You can define classes that hide both data and operations from any methods that are not part of the class. You can then implement whatever interface is most appropriate for the intended use.
2-6
MATLAB Classes
Using Objects to Write Data to a File on page 2-18 shows advantages of using objects to define certain operations and how smoothly object fit in a function-oriented workflow. Example Representing Structured Data on page 2-22 shows the application of object-oriented techniques to managing data. Example Implementing Linked Lists on page 2-31 using a handle class to implement a doubly linked list.
2-7
Code Examples
2-8
(Continued) Background Information and Discussion Attribute Tables Creating Subclasses Syntax and Techniques on page 10-7 Modifying Superclass Methods and Properties on page 10-13 Kinds of classes Comparing Handle and Value Classes on page 5-2 The Handle Superclass on page 5-11 a detailed description of the abstract class. Properties Defining Properties on page 6-5 for an overview of what properties are and how to use them Property Definition Block on page 6-5 shows how to specify initial values Attributes Specifying Property Attributes on page 6-7 for a list of property attributes Dynamic Properties Adding Properties to an Instance on page 6-21 Methods Class Methods on page 7-2 for an overview of methods Attributes Method Attributes on page 7-4 for a list of method attributes Restricting Properties to Specific Values on page 2-25 Dependent Properties on page 2-27 Example Implementing Linked Lists on page 2-31 Specializing the dlnode Class on page 2-40
Code Examples
2-9
(Continued) Background Information and Discussion Attribute Tables Class Constructor Methods on page 7-15 for information about constructor methods Handle Class Delete Methods on page 5-15 Property Set and Get Access Methods on page 6-12 Implementing a Set/Get Interface for Properties on page 5-21 Events Events and Listeners Concepts on page 9-9 for an overview of how events work Defining Events and Listeners Syntax and Techniques on page 9-15 for the syntax used to define events and listeners Example Using Events to Update Graphs on page 9-30 for a complete example that uses events and listeners, including a property listener Restricting Properties to Specific Values on page 2-25 Simplifying the Interface with a Constructor on page 2-26
Code Examples
2-10
Formulating a Class
This example discusses the design and implementation of a simple class. To design a class that represents a bank account, first determine the elements of data and the operations that form your abstraction of a bank account. For example, a bank account has: An account number An account balance A current status (open, closed, etc.) You need to perform certain operations on a bank account: Deposit money Withdraw money You might also want the bank account to send a notice if the balance is too low and an attempt is made to withdraw money. When this event occurs, the bank account can broadcast a notice and other entities that are designed to listen for these notices, such as an account manager program, can take action. In this case, the status of all bank accounts is determined by an account manager program that looks at the account balance and assigns one of three values: open Account balance is a positive value overdrawn Account balance is overdrawn, but by $200 or less. closed Account balance is overdrawn by more than $200.
2-11
In MATLAB classes, data is stored in properties, operations are implemented with methods, and notifications are supported with events and listeners. Therefore, the bank account class needs the components discussed in the following sections.
2-12
Class Definition
classdef BankAccount < handle properties (Hidden) AccountStatus = 'open'; end % The following properties can be set only by class methods
2-13
properties (SetAccess = private) AccountNumber AccountBalance = 0; end % Define an event called InsufficientFunds events InsufficientFunds end methods function BA = BankAccount(AccountNumber,InitialBalance) BA.AccountNumber = AccountNumber; BA.AccountBalance = InitialBalance; % Calling a static method requires the class name % addAccount registers the InsufficientFunds listener on this instance AccountManager.addAccount(BA); end function deposit(BA,amt) BA.AccountBalance = BA.AccountBalance + amt; if BA.AccountBalance > 0 BA.AccountStatus = 'open'; end end function withdraw(BA,amt) if (strcmp(BA.AccountStatus,'closed')&& BA.AccountBalance < 0) disp(['Account ',num2str(BA.AccountNumber),' has been closed.']) return end newbal = BA.AccountBalance - amt; BA.AccountBalance = newbal; % If a withdrawal results in a negative balance, % trigger the InsufficientFunds event using notify if newbal < 0 notify(BA,'InsufficientFunds') end end % withdraw end % methods end % classdef
2-14
Class Definition
classdef AccountManager methods (Static) function assignStatus(BA) if BA.AccountBalance < 0 if BA.AccountBalance < -200 BA.AccountStatus = 'closed'; else BA.AccountStatus = 'overdrawn'; end end end function addAccount(BA) % Call the handle addlistener method % Object BA is a handle class addlistener(BA, 'InsufficientFunds', ... @(src, evnt)AccountManager.assignStatus(src)); end end end
Note that the AccountManager class is never instantiated. It serves as a container for the event listener used by all BankAccount objects.
2-15
Now suppose you make a withdrawal of $600, which results in a negative account balance:
BA.withdraw(600) BA.AccountBalance ans = -100 BA.AccountStatus ans = overdrawn
When the $600 withdrawal occurred, the InsufficientsFunds event was triggered. Because the AccountBalance is not less than $200, the AccountStatus was set to overdrawn:
BA.withdraw(200) BA.AccountBalance ans = -300 BA.AccountStatus ans = closed
Now the AccountStatus has been set to closed by the listener and further attempts to make withdrawals are blocked:
BA.withdraw(100) Account 1234567 has been closed
If the AccountBalance is returned to a positive value by a deposit, then the AccountStatus is returned to open and withdrawals are allowed again:
BA.deposit(700)
2-16
2-17
Flexible Workflow
The MATLAB language does not require you to define classes for all the code you write. You can use objects along with ordinary functions. This section illustrates the use of an object that implements the basic task of writing text to a file. Then this object is used in a function to write a text file template for a class definition.
2-18
This class is derived from the handle class so that a Filewriter object is a handle object. All copies of handle objects reference the same internal data so there will be only one file identifier in use, even if you make copies of the object. Also, handle classes define a delete method which is called automatically when a handle object is destroyed. This example overrides the delete method to close the file before the file identifier is lost and the file is left open.
classdef Filewriter < handle % Property data is private to the class properties (SetAccess = private, GetAccess = private) FileID end % properties methods % Construct an object and % save the file ID function obj = Filewriter(filename) obj.FileID = fopen(filename,'a'); end function writeToFile(obj,text_str) fprintf(obj.FileID,'%s\n',text_str); end % Delete methods are always called before a object % of the class is destroyed function delete(obj) fclose(obj.FileID); end end % methods end % class
2-19
>> fw.writeToFile('classdef mynewclass < handle') >> clear fw >> type mynewclass classdef mynewclass < handle
This example creates only one simple class template, but another version might accept a cell array of attribute name/value pairs, method names, and so on.
function writeClassFile(classname,superclass) % Use a Filewriter object to write text to a file fw = Filewriter([classname '.m']); if nargin > 1 fw.writeToFile(['classdef ' classname ' < ' superclass]) else fw.writeToFile(['classdef ' classname]) end fw.writeToFile(' properties ') fw.writeToFile(' ') fw.writeToFile(' end % properties') fw.writeToFile(' ') fw.writeToFile(' methods ') fw.writeToFile([' function obj = ' classname '()']) fw.writeToFile(' ') fw.writeToFile(' end') fw.writeToFile(' end % methods') fw.writeToFile('end % classdef') delete(fw) % Delete object, which closes file end
To create a class file template, call writeClassFile with the name of the new class and its superclass. Use the type command to display the contents of the file:
2-20
>> writeClassFile('myNewClass','handle') >> type myNewClass classdef myNewClass < handle properties end % properties methods function obj = myNewClass() end end % methods end % classdef
2-21
2-22
Data
Material SampleNumber Stress Strain Modulus
Description Character string identifying the type of material tested Number of a particular test sample Vector of doubles representing the stress applied to the sample during the test. Vector of doubles representing the strain at the corresponding values of the applied stress. Double defining an elastic modulus of the material under test, which is calculated from the stress and strain data
2-23
classdef TensileData properties Material = ''; SampleNumber = 0; Stress Strain Modulus = 0; end end
would simply add a new field to a structure array, but returns an error when td is an instance of the TensileData class. A class is easy to reuse. Once you have defined the class, you can easily extend it with subclasses that add new properties.
2-24
A class is easy to identify. A class has a name so that you can identify objects with the whos and class functions and the Workspace browser. The class name makes it easy to refer to records with a meaningful name. A class can validate individual field values when assigned, including class or value. A class can restrict access to fields, for example, allowing a particular field to be read, but not changed. The next section describes how to add type checking and how to restrict property access in the TensileData class.
2-25
When an attempt is made to set the Material property, the MATLAB runtime passes the object and the specified value to the propertys set.Material function (the obj and the material input arguments). In this case, if the value does not match the acceptable values, the function returns an error. Otherwise, the specified value is used to set the property. Only the set method can directly access the property in the object (without calling the property set method). For example:
>>td = TensileData; >>td.Material = 'composite'; ??? Error using ==> TensileData.TensileData>Material_set__ Material must be aluminum, stainless steel, or carbon steel
2-26
Using the constructor, you can create a TensileData object fully populated with data using the following statement:
td = TensileData('carbon steel',1,[2e4 4e4 6e4 8e4],[.12 .20 .31 .40]);
Calculating Modulus
Note that the constructor function does not have an input argument for the value of the Modulus property. This is because the value of the Modulus: Is easy to calculate from the Stress and Strain property values Needs to change if the value of the Stress or Strain property changes Therefore, it is better to calculate the value of the Modulus property only when its value is requested. You can do this with a property get access method, which is described in the next section.
Dependent Properties
TensileData objects do not store the value of the Modulus property; instead this value is calculated whenever it is requested. This approach enables you to update the Stress and Strain property data at any time without having to recalculate the value of the Modulus property.
2-27
methods function modulus = get.Modulus(obj) ind = find(obj.Strain > 0); % Find nonzero strain modulus = mean(obj.Stress(ind)./obj.Strain(ind)); end % Modulus get method end % methods
This function simply calculates the average ratio of stress to strain data after eliminating zeros in the denominator data. The MATLAB runtime calls the get.Modulus method when the property is queried. For example,
td = TensileData('carbon steel',1,[2e4 4e4 6e4 8e4],[.12 .20 .31 .40]); td.Modulus ans = 1.9005e+005
2-28
Strain property data since these properties contain raw data that is not easily viewed in the command window. The plot method (described in the
next section) provides a better way to display stress and strain data. The disp method uses fprintf to display formatted text in the command window:
methods function disp(td) fprintf(1,'Material: %s\nSample Number: %g\nModulus: %1.5g\n',... td.Material,td.SampleNumber,td.Modulus); end % disp end % methods
The first argument to this method is a TensileData object, which contains the data and is used by the MATLAB runtime to dispatch to the TensileData class plot method and not the built-in plot function. The variable list of arguments that follow are passed directly to the built-in plot function from within the method. This enables the TensileData plot method to behave like the built-in plot function, which allows you to pass line specifier arguments or property name/value pairs along with the data.
2-29
2-30
Encapsulation
This example shows how classes encapsulate the internal structure used to implement the class design (a doubly linked lists). Encapsulation conceals the internal workings of the class from other code and provides a stable interface to programs that use this class. It also prevents client code from misusing the class because only class methods can access certain class data.
2-31
Class methods define the operations that you can perform on nodes of this class. These methods hide the potentially confusing process of inserting and removing nodes, while at the same time providing an interface that performs operations simply: Creating a node by passing the constructor a data value Inserting nodes with respect to other nodes in the list (before or after) Removing nodes from the list See Defining the dlnode Class on page 2-35 for the implementation details.
Class Properties
The dlnode class implements each node as a handle object with three properties:
2-32
Data Contains the data for this node Next Contains the handle of the next node in the list (SetAccess = private) Prev Contains the handle of the previous node in the list (SetAccess = private) This diagram shows a three-node list n1, n2, and n3. It also shows how the nodes reference the next and previous nodes.
Class Methods
The dlnode class implements the following methods: dlnode Constructs a node and assigns the value passed as input to the Data property insertAfter Inserts this node after the specified node insertBefore Inserts this node before the specified node disconnect Removes this node from the list disp Overloads default disp function so that the Data property displays on the command line for scalar objects and the dimension of the array displays for object arrays delete Removes this node from the list before it is destroyed
2-33
You build these nodes into a doubly linked list using the class methods:
n2.insertAfter(n1) n3.insertAfter(n2)
Now the three nodes are linked. The dlnode disp method returns the data for the node referred to:
n1.Next % Points to n2 ans = Doubly-linked list node with data: 2 n2.Next.Prev % Points back to n2 ans = Doubly-linked list node with data: 2 n1.Next.Next % Points to n3 ans = Doubly-linked list node with data: 3 n3.Prev.Prev % Points to n1 ans = Doubly-linked list node with data: 1
2-34
But each instance of a node is unique so there is only one node in the list that can satisfy the conditions of being equal to n1.Next and having a Prev property that contains a handle to n1. Therefore, x must point to the same node as n2. This means there has to be a way for multiple variables to refer to the same object. The MATLAB handle class provides a means for both x and n2 to refer to the same node. All instances of the handle class are handles that exhibit the copy behavior described previously. Notice that the handle class defines the eq method (use methods('handle') to list the handle class methods), which enables the use of the == operator with all handle objects. See Comparing Handle and Value Classes on page 5-2 for more information on kinds of MATLAB classes. See The Handle Superclass on page 5-11 for more information about the handle class.
2-35
Class Properties
The dlnode class is itself a handle class because it is derived from the handle class. Note that only class methods can set the Next and Prev properties (SetAccess = private). Using private set access prevents client code from performing any incorrect operation with these properties. The dlnode class defines methods that perform all the operations that are allowed on these nodes. Here are the property definition blocks:
classdef dlnode < handle properties Data end properties (SetAccess = private) Next Prev end
When you add the node to a list, the class methods that perform the insertion set the Next and Prev properties. See Inserting Nodes on page 2-38.
Disconnecting Nodes
The disconnect method removes a node from a list and repairs the list by reconnecting the appropriate nodes. The insertBefore and insertAfter methods always call disconnect on the node to insert before attempting to connect it to a linked list. This ensures the node is in a known state before assigning it to the Next or Prev property:
function disconnect(node) if ~isscalar(node)
2-36
error('Nodes must be scalar') end prevNode = node.Prev; nextNode = node.Next; if ~isempty(prevNode) prevNode.Next = nextNode; end if ~isempty(nextNode) nextNode.Prev = prevNode; end node.Next = []; node.Prev = []; end
For example, suppose you remove n2 from the three-node list discussed above (n1 n2 n3):
n2.disconnect; disconnect removes n2 from the list and repairs the list with the following
steps:
n1 = n2.Prev; n3 = n2.Next; if n1 exists, then n1.Next = n3; if n3 exists, then n3.Prev = n1
Now the list is rejoined because n1 connects to n3 and n3 connects to n1. The final step is to ensure that n2.Next and n2.Prev are both empty (i.e., n2 is not connected):
% These properties have private SetAccess % so they can be set only within class methods n2.Next = []; n2.Prev = [];
2-37
Inserting Nodes
There are two methods for inserting nodes into the listinsertAfter and insertBefore. These methods perform similar operations, so this section describes only insertAfter in detail.
methods function insertAfter(newNode,nodeBefore) disconnect(newNode); newNode.Next = nodeBefore.Next; newNode.Prev = nodeBefore; if ~isempty(nodeBefore.Next) nodeBefore.Next.Prev = newNode; end nodeBefore.Next = newNode; end
How insertAfter Works. First insertAfter calls the disconnect method to ensure that the new node is not connected to any other nodes. Then, it assigns the newNode Next and Prev properties to the handles of the nodes that are after and before the newNode location in the list. For example, suppose you want to insert a new node, nnew, after an existing node, n1, in a list containing n1 n2. First, create nnew:
nnew = dlnode(rand(3));
Next, call insertAfter to insert nnew into the list after n1:
nnew.insertAfter(n1)
The insertAfter method performs the following steps to insert nnew in the list between n1 and n2:
% n1.Next is currently n2, set nnew.Next to n1.Next (which is n2) nnew.Next = n1.Next; % nnew.Prev must be set to n1 nnew.Prev = n1; % if n1.Next is not empty, then % n1.Next is still n2, so n1.Next.Prev is n2.Prev, which is set to nnew
2-38
2-39
The dlnode class defines a delete method because each dlnode object is a node in a doubly linked list. If a node object is going to be destroyed, the delete method must disconnect the node and repair the list before allowing MATLAB to destroy the node. The disconnect method already performs the necessary steps, so the delete method can simply call disconnect:
function delete(node) disconnect(node); end
2-40
n = n@dlnode(data); % Initialize a dlnode object n.Name = name; end function disp(node) % Extend the dlnode disp method if (isscalar(node)) disp(['Node Name: ' node.Name]) disp@dlnode(node); % Call dlnode disp method else disp@dlnode(node); end end end % methods end % classdef
The NamedNode class adds a Name property to store the node name and extends the disp method defined in the dlnode class. The constructor calls the class constructor for the dlnode class, and then assigns a value to the Name property. The NamedNode class defines default values for the properties for cases when MATLAB calls the constructor with no arguments. See Basic Structure of Constructor Methods on page 7-22 for more information on defining class constructor methods.
Now use the insert methods inherited from dlnode to build the list:
n(2).insertAfter(n(1))
2-41
n(3).insertAfter(n(2))
A single node displays its name and data when you query its properties:
>> n(1).Next ans = Node Name: Second Node Doubly-linked list node with data: 200 >> n(1).Next.Next ans = Node Name: Third Node Doubly-linked list node with data: 300 >> n(3).Prev.Prev ans = Node Name: First Node Doubly-linked list node with data: 100
If you display an array of nodes, the NamedNode disp method displays only the dimensions of the array:
>> n n = 1x3 array of doubly-linked list nodes
2-42
2-43
FofXY % function handle Lm = [-2*pi 2*pi]; % Initial limits end % properties properties (Dependent = true, SetAccess = private) Data end % properties Dependent = true, SetAccess = private methods function obj = topo(fnc,limits) % Constructor assigns property values obj.FofXY = fnc; obj.Lm = limits; end % topo function set.Lm(obj,lim) % Lm property set function if else obj.Lm = lim; end end % set.Lm function data = get.Data(obj) % get function calculates Data % Use class name to call static method [x,y] = topo.grid(obj.Lm); matrix = obj.FofXY(x,y); data.X = x; data.Y = y; data.Matrix = matrix;% Return value of property end % get.Data function surflight(obj) % Graph function as surface obj.FigHandle = figure; surfc(obj.Data.X,obj.Data.Y,obj.Data.Matrix,... 'FaceColor',[.8 .8 0],'EdgeColor',[0 .2 0],... 'FaceLighting','phong'); ~(lim(1) < lim(2)) error('Limits must be monotonically increasing')
2-44
camlight left; material shiny; grid off colormap copper end % surflight method function delete(obj) % Delete the figure h = obj.FigHandle; if ishandle(h) delete(h); else return end end % delete end % methods methods (Static = true) % Define static method function [x,y] = grid(lim) inc = (lim(2)-lim(1))/35; [x,y] = meshgrid(lim(1):inc:lim(2)); end % grid end % methods Static = true end % topo class
To create an instance of the class, passing a function handle and a vector of limits to the constructor. The easiest way to create a function handle for these functions is to use an anonymous function:
2-45
The class surflight method uses the object to create a graph of the function. The actual data required to create the graph is not stored. When the surflight method accesses the Data property, the propertys get function performs the evaluation and returns the data in the Data property structure fields. This data is then plotted. The advantage of not storing the data is the reduced size of the object.
Now suppose you change the FofXY property so that it contains a function handle that points to another function:
2-46
Because a is a copy of the handle object tobj, changes to the data referenced by tobj also change the data referenced by a.
2-47
2-48
3
Class DefinitionSyntax Reference
Class Folders on page 3-2 Class Components on page 3-5 The Classdef Block on page 3-6 Specifying Properties on page 3-8 Specifying Methods and Functions on page 3-13 Events and Listeners on page 3-19 Specifying Attributes on page 3-21 Calling Superclass Methods on Subclass Objects on page 3-24 A Class Code Listing on page 3-27 Understanding Code Analyzer Warnings on page 3-29 Functions Used with Objects on page 3-32 Using the Editor and Debugger with Classes on page 3-33 Modifying and Reloading Classes on page 3-34 Compatibility with Previous Versions on page 3-37 MATLAB Vs. Other OO Languages on page 3-41
Class Folders
In this section... Options for Class Folders on page 3-2 Grouping Classes with Package Folders on page 3-3 More Information on Class Folders on page 3-4
pathfolder ClassNameA.m ClassNameB.m ClassNameC.m ... ordinaryFunction.m Contains classdef and methods for ClassNameA Contains classdef and methods for ClassNameB Contains classdef and methods for ClassNameC A function on the path
See Methods in Separate Files on page 7-7 for more information on using multiple files to define classes.
3-2
Class Folders
pathfolder @ClassNameA ClassNameA.m classMethod.m ClassNameB.m Contains classdef Class method in separate file Contains entire class definition
A path folder can contain classes defined in both @-folders and single files without an @-folder.
3-3
pathfolder +packagefld1 @ClassNameA ClassNameA.m classMethod.m ClassNameB.m +packagefld2 packageFunction.m ClassNameA.m ClassNameB.m Contains classdef Class method in separate file Contains entire class definition Defines a new name space
3-4
Class Components
Class Components
In this section... Class Building Blocks on page 3-5 More In Depth Information on page 3-6
properties block (one for each unique set of attribute specifications) contains property definitions, including optional initial values. The properties block starts with the properties keyword and terminates with the end keyword. See Specifying Properties on page 3-8 for more syntax information.
classdef ClassName properties ... end ... end
methods block (one for each unique set of attribute specifications) contains function definitions for the class methods. The methods block starts with the methods keyword and terminates with the end keyword. See The Methods Block on page 3-13 for more syntax information.
classdef ClassName methods ...
3-5
events block (one for each unique set of attribute specifications) contains the names of events that this class declares. The events blocks starts with the events keyword and terminates with the end keyword. See Specifying Events on page 3-19 for more syntax information.
classdef ClassName events ... end ... end properties, methods, and events are keywords only within a classdef block.
3-6
See Class Attributes on page 4-5 for a list of attributes and a discussion of the behaviors they control.
Specifying Superclasses
To define a class in terms of one or more other classes by specifying the superclasses on the classdef line:
classdef class_name < superclass_name ... end
See Creating Subclasses Syntax and Techniques on page 10-7 for more information.
3-7
Specifying Properties
In this section... What You Can Define on page 3-8 How to Initialize Property Values on page 3-8 Defining Default Values on page 3-9 Assigning Property Values from Within the Constructor on page 3-9 Initializing Properties to Unique Values on page 3-10 Property Attributes on page 3-10 Property Access Methods on page 3-11 Referencing Object Properties Using Variables on page 3-11
3-8
Specifying Properties
Evaluation of property default values occurs only when the value is first needed, and only once when MATLAB first initializes the class. MATLAB does not reevaluate the expression each time you create a class instance. See Using Expressions in Class Definitions on page 4-7 for more information on how MATLAB evaluates expressions that you use to assign property default values. MATLAB sets property values not specified in the class definition to empty ([]).
3-9
When you assign an object property from the class constructor, MATLAB evaluates the assignment statement for each instance created. Assign property values in the constructor if you want each object to contain a unique instance of a handle object. See Referencing the Object in a Constructor on page 7-17 for more information on constructor methods.
Property Attributes
All properties have attributes that modify certain aspects of the propertys behavior. Specified attributes apply to all properties in a particular properties block. For example:
classdef class_name properties
PropertyName % No default value assigned PropertyName = sin(pi/12); % Expression returns default value
end properties (SetAccess = private, GetAccess = private) Stress Strain end end
In this case, only methods in the same class definition can modify and query the Stress and Strain properties. This restriction exists because the class defines these properties in a properties block with SetAccess and GetAccess attributes set to private.
3-10
Specifying Properties
MATLAB does not call the property set access method when assigning the default value specified in the propertys definition block. If a handle class defines the property, the set access method does not need to return the modified object. Property Access Methods on page 6-12 for more information on these methods. Defining Properties on page 6-5 for information on properties.
where PropertyNameVar is a variable containing the name of a valid object property. Use this syntax when passing property names as arguments:
PropName = 'KeyType';
3-11
function o = getPropValue(obj,PropName) ... o = obj.(PropName); % Returns value of KeyType property ... end
3-12
3-13
3-14
Converter methods that convert to classes contained in packages, which must use the package name as part of the class name. Property set and get access methods (Property Access Methods on page 6-12)
Include the method signature in the file with the classdef block only if you want to specify attributes for that method. Otherwise, you can implement the method as a function in a separate file in the @-folder.
3-15
You would then define the functions in separate files using the same function signature. For example:
function output = staticFunc1(arg1,arg2) ... end
For an Example
The example, Example Using Events to Update Graphs on page 9-30 uses multiple files for class definition.
3-16
- end block, but in the same file as the class definition. Subfunctions defined in classdef files work like subfunctions. You can call these subfunctions from anywhere in the same file, but they are not visible outside of the file in which you define them.
Subfunctions in classdef files are useful for utility functions that you use only within that file. These functions can take or return arguments that are instances of the class but, it is not necessary, as in the case of ordinary methods. For example, the following code defines myUtilityFcn outside the classdef block:
classdef MyClass properties PropName end methods function obj = MyClass(arg1) obj.PropName = arg1; end end % methods end % classdef function myUtilityFcn ... end
You also can create package functions, which require you to use the package name when calling these functions. See Scoping Classes with Packages on page 4-19 for more information on packages
3-17
See the handle class for a list of operations defined for that class, which are inherited by all classes deriving from handle.
3-18
Specifying Events
To define an event, you declare a name for the event in the events block. Then one of the class methods triggers the event using the notify method, which is method inherited from the handle class. Only classes derived from the handle class can define events. For example, the following class: Defines an event named StateChange Triggers the event using the inherited notify method.
classdef class_name < handle % Subclass handle events % Define an event called StateChange StateChange end ... methods function upDateGUI(obj) ... % Broadcast notice that StateChange event has occurred notify(obj,'StateChange'); end end end
3-19
these functions. To register a listener callback, use the addlistener method of the handle class.
addlistener(event_obj,'StateChange',@myCallback)
See Defining Events and Listeners Syntax and Techniques on page 9-15
3-20
Specifying Attributes
Specifying Attributes
In this section... Attribute Syntax on page 3-21 Attribute Descriptions on page 3-21 Specifying Attribute Values on page 3-22 Simpler Syntax for true/false Attributes on page 3-22
Attribute Syntax
For a quick reference to all attributes, see Attribute Tables. Attributes modify the behavior of classes and class components (properties, methods, and events). Attributes enable you to define useful behaviors without writing complicated code. For example, you can create a read-only property by setting its SetAccess attribute to private, but leaving its GetAccess attribute set to public (the default):
properties (SetAccess = private) ScreenSize = getScreenSize; end
All class definition blocks (classdef, properties, methods, and events) support specific attributes and all attributes have default values. Specify attribute values only in cases where you want to change from the default value to another predefined value.
Attribute Descriptions
For lists of supported attributes, see: Class Attributes on page 4-5 Property Attributes on page 6-8 Method Attributes on page 7-4 Event Attributes on page 9-14
3-21
Specified multiple attributes in a comma-separated list, as shown in the previous example. When specifying class attributes, place the attribute list directly after the classdef keyword:
classdef (Sealed = true) myclass ... end
3-22
Specifying Attributes
All attributes that take a logical value (that is, true or false) have a default value of false. Therefore, specify an attribute only if you want to set it to true.
3-23
Interpret this syntax as meaning, the MySub object arrives at the MySuperClass constructor , which constructs the MySuperClass part of the object using the specified arguments.
3-24
obj = obj@MySuperClass(SuperClassArguments);
3-25
superMethod@MySuperClass(obj)
3-26
3-27
if result == false notify(obj,'BackgroundAlert'); end end function jobt = get.JobTitle(obj) jobt = currentJT(obj.EmpNumber); end function set.OfficeNumber(obj,setvalue) if isInUse(setvalue) error('Not available') else obj.OfficeNumber = setvalue; end end end methods (Static) function num = getEmpNumber num = queryDB('LastEmpNumber') + 1; end end end
3-28
While the previous function is legal MATLAB code, it results in Code Analyzer warnings for two reasons: The value of EmployeeName is never used EmployeeName is the name of a property that is used as a variable
3-29
The Code Analyzer returns only one warning, suggesting that you might actually want to refer to the EmployeeName property. While this version of someMethod is legal MATLAB code, it is confusing to give a property the same name as a function. Therefore, the Code Analyzer provides a warning suggesting that you might have intended the statement to be:
EN = obj.EmployeeName;
M-Lint does not warn when a variable name is the same as a property name when the variable is: An input or output variable A global or persistent variable In these particular cases, M-Lint does not warn you that you are using a variable name that is also a property name. Therefore, a coding error like the following:
3-30
3-31
Purpose Return class of object List of event names defined by the class List of methods implemented by the class Information on class methods in separate window List of class property names
Purpose Determine whether argument is object of specific class Determine if two objects are equal, which means both objects are of the same class and size and their corresponding property values are equal Determine whether input is MATLAB object
isobject
3-32
To open myclass.m in the MATLAB editor, you could reference the file using dot-separated package names:
edit PackFld1.PackFld2.myclass
To refer to a function defined in its own file inside of a class @-folder, use:
edit +PackFld1/+PackFld2/@myclass/myMethod
3-33
Modifying a class definition includes doing any of the following: Changing class member attributes Adding, deleting, or changing the names of properties, methods, or events Changing class inheritance Changing the definition of a superclass (requires you to clear subclass objects) If there are no class instances, MATLAB applies changes in the code immediately. If there are instances, you must clear those objects before MATLAB applies your changes.
Clear Classes
When you issue the clear classes command, MATLAB clears: The current workspace of all variables All functions, which can have persistent variables holding class instances (unless the function is locked)
3-34
All classes that are not instantiated However, it is possible that your MATLAB session is holding instances of the class that the clear classes command does not clear. For example, suppose you change the definition of MyClass after saving an instance of this class in a Handle Graphics objects UserData property:
obj = MyClass; % User-defined class that you are editing h = uicontrol('Style','pushbutton'); set(h,'UserData',obj) clear classes Warning: Objects of 'MyClass' class exist. Cannot clear this class or any of its super-classes.
MATLAB issues a warning stating that it cannot apply your changes because it cannot clear the class. Clear the instance of MyClass before calling clear classes. For example, you can use the close all command to remove the object or reset the UserData property to another value:
% First, get the handle of the uicontrol, which was cleared h = findobj('Type','uicontrol','Style','pushbutton'); set(h,'UserData',[])
3-35
Locked Functions. Functions can contain objects in their workspace. If the function is locked (with mlock), unlock it (using munlock) so that MATLAB can clear the instance. Use clear functions once you have unlocked the function. Default Property Values. When you specify a default value in a properties definition block, MATLAB evaluates the expression that defines the default value once when loading the class. Clear this value using the clear classes command. Constant Properties. When you define a constant property (property Constant attribute set to true) whose value is an object, MATLAB creates the instance when loading the class. Clear this instance using the clear classes command. Handle Graphics Objects. Handle Graphics objects can contain class instances in UserData properties, in Application Data, or created in callback functions. Issuing the close all command removes the Handle Graphics objects, unless these objects enable hidden handles. See the close command for more information. You can remove Application Data using the rmappdata function. Simulink Models. Models can contain class instances. Use close_system to close the model so that MATLAB can apply your changes.
3-36
3-37
Private Methods
You do not need to define private folders in class folders in Version 7.6. You can set the methods Access attribute to private instead.
Write the same Stock class constructor as shown here. Define the inheritance on the classdef line and define the constructor within a methods block. Constructor Function for Version 7.6
classdef Stock < Asset ... methods function s = Stock(description,num_shares,share_price) % Call superclass constructor to pass arguments
3-38
s = s@Asset(description,'stock',share_price*num_shares); s.NumShares = num_shares; s.SharePrice = share_price; end % End of function end % End of methods block end % End of classdef block
3-39
Example A Polynomial Class on page 16-2 Example A Simple Class Hierarchy on page 17-2 Example Containing Assets in a Portfolio on page 17-19
Obsolete Documentation
Documentation for MATLAB Classes and Objects before Version 7.6 is available here.
3-40
Public Properties
Unlike fields in C++ or the Java language, you can use MATLAB properties to define a public interface separate from the implementation of data storage. You can provide public access to properties because you can define set and get access methods that execute automatically when assigning or querying property values. For example, the following statement:
myobj.Material = 'plastic';
assigns the string plastic to the Material property of myobj. Before making the actual assignment, myobj executes a method called set.Material (assuming the class of myobj defines this method), which can perform any necessary operations. See Property Set and Get Access Methods on page 6-12 for more information on property access methods. You can also control access to properties by setting attributes, which enable public, protected , or private access. See Property Attributes on page 6-8 for a full list of property attributes.
No Implicit Parameters
In some languages, one object parameter to a method is always implicit. In MATLAB, objects are explicit parameters to the methods that act on them.
3-41
Dispatching
In MATLAB classes, method dispatching is not based on method signature, as it is in C++ and Java code. When the argument list contains objects of equal precedence, MATLAB software uses the left-most object to select the method to call. However, if the class of that argument is superior to the other arguments, MATLAB can dispatch to a method of an argument in any position within an argument list. See Specifying Class Precedence on page 4-17 for more information.
In Java code, you use: superclass.method The equivalent MATLAB operation is method@superclass.
Other Differences
In MATLAB classes, there is no equivalent to C++ templates or Java generics. However, MATLAB is weakly typed and it is possible to write functions and classes that work with different types of data. MATLAB classes do not support overloading functions using different signatures for the same function name.
Modifying Objects
MATLAB classes can define public properties, which you can modify by explicitly assigning values to those properties on a given instance of the class. However, only classes derived from the handle class exhibit reference behavior. Modifying a property value on an instance of a value classes (classes not derived from handle), changes the value only within the context in which the modification is made. The sections that follow describe this behavior in more detail.
3-42
3-43
end
Pass the object to the function g, which assigns blue to the Color property:
function y = g(x) x.Color = 'blue'; y = x; end y = g(obj);
The function g modifies its copy of the input object and returns that copy, but does not change the original object.
y.Color ans = blue obj.Color ans = red
If the function g did not return a value, the modification of the object Color property would have occurred only on the copy of obj within the function workspace. This copy would have gone out of scope when the function execution ended. Overwriting the original variable actually replaces it with a new object:
obj = g(obj);
3-44
Passing Handle Objects. When you pass a handle to a function, the function makes a copy of the handle variable, just like when passing a value object. However, because a copy of a handle object refers to the same object as the original handle, the function can modify the object without having to return the modified object. For example, suppose you modify the SimpleClass class definition to make a class derived from the handle class:
classdef SimpleHandleClass < handle properties Color end methods function obj = SimpleHandleClass(c) if nargin > 0 obj.Color = c; end end end end
Pass the object to the function g, which assigns blue to the Color property:
y = g(obj);
The function g sets the Color property of the object referred to by both the returned handle and the original handle:
y.Color ans = blue obj.Color
3-45
ans = blue
The function g modified the object referred to by the input argument (obj) and returned a handle to that object in y. MATLAB Passes Handles by Value. A handle variable is a reference to an object. MATLAB passes this reference by value. Handles do not behave like references in C++. If you pass an object handle to a function and that function assigns a different object to that handle variable, the variable in the caller is not affected. For example, suppose you define a function g2:
function y = g2(x) x = SimpleHandleClass('green'); y = x; end
3-46
red
The function overwrites the handle passed in as an argument, but does not overwrite the object referred to by the handle. The original handle obj still references the original object.
3-47
Technique Reference/reference classes Abstract class/Interface Garbage collection Instance properties Importing classes Events and Listeners
How to Use in MATLAB Comparing Handle and Value Classes on page 5-2 Abstract Classes and Interfaces on page 10-50 Object Lifecycle on page 5-16 Dynamic Properties Adding Properties to an Instance on page 6-21 Importing Classes on page 4-24 Events and Listeners Concepts on page 9-9
3-48
4
Defining and Organizing Classes
Class Overview on page 4-2 Defining Classes Syntax on page 4-4 Class Attributes on page 4-5 Using Expressions in Class Definitions on page 4-7 Organizing Classes in Folders on page 4-13 Specifying Class Precedence on page 4-17 Scoping Classes with Packages on page 4-19 Importing Classes on page 4-24
Class Overview
MATLAB User-Defined Classes
A MATLAB class definition is a template whose purpose is to provide a description of all the elements that are common to all instances of the class. Class members are the properties, methods, and events that define the class. MATLAB classes are defined in code blocks, with sub-blocks delineating the definitions of various class members. See classdef Syntax on page 4-4 for details on the classdef block.
Kinds of Classes
There are two kinds of MATLAB classeshandle and value classes. Handle classes create objects that reference the data contained. Copies refer to the same data. Value classes make copies of the data whenever the object is copied or passed to a function. MATLAB numeric types are value classes.
4-2
Class Overview
See Comparing Handle and Value Classes on page 5-2 for a more complete discussion.
Constructing Objects
For information on class constructors, see Class Constructor Methods on page 7-15 For information on creating arrays of objects, see Creating Object Arrays on page 8-3
4-3
classdef (ConstructOnLoad = true) PositiveIntegers < Integers & Positives ... end classdef block
Class attribute
Class name
Super classes
4-4
Class Attributes
Class Attributes
In this section... Table of Class Attributes on page 4-5 Specifying Attributes on page 4-6
Class
logical
Description If true, this class does not appear in the output of MATLAB commands or tools that display class names. Use this attribute to establish a precedence relationship among classes. Specify a cell array of meta.class objects using the ? operator. The built-in classes double, single, char, logical, int64, uint64, int32, uint32, int16, uint16, int8, uint8, cell, struct, and function_handle are always inferior to user-defined classes and do not show up in this list. See Specifying Class Precedence on page 4-17 If true, MATLAB calls the class constructor when loading an object from a MAT-file. Therefore, you must implement the constructor so it can be called with no arguments without producing an error. See Calling Constructor When Loading on page 11-25 If true, this class can not be subclassed.
(default =
false) InferiorClasses cell
(default = {})
ConstructOnLoad
logical
(default =
false)
Sealed
logical
(default =
false)
4-5
Specifying Attributes
Attributes are specified for class members in the classdef, properties, methods, and events definition blocks. The particular attribute setting applies to all members defined within that particular block. This means that, for example, you might use multiple properties definition blocks so you can apply different attribute setting to different properties.
Attribute Syntax
Specify class attribute values in parentheses, separating each attribute name/attribute value pair with a comma. The attribute list always follows the classdef or class member key word, as shown below:
classdef (attribute-name = expression, ...) ClassName properties (attribute-name = expression, ...) ... end methods (attribute-name = expression, ...) ... end events (attribute-name = expression, ...) ... end end
4-6
Basic Knowledge
Expressions, Evaluating Expressions, Specifying Properties on page 3-8, Specifying Attributes on page 3-21.
MATLAB does not call property set methods when assigning the result of default value expressions to properties. (See Property Set and Get Access Methods on page 6-12 for information about these special methods.)
4-7
It is possible to use a MATLAB expression on the right side of the equals sign (=) as long as it evaluates to logical true or false. However, this expression cannot use any definitions in its own file, including any constant properties, static methods, and local functions. While it is possible to use conditional expressions to specify attribute values, doing so can cause the class definition to change based on external conditions. See Specifying Attributes on page 3-21 for more information on attribute syntax.
4-8
4-9
MATLAB creates an instance of the ContClass class when the ClassExp class is first used. MATLAB initializes both classes at this time. All instances of ClassExp include a copy of this same instance of ContClass.
a = ClassExp; a.ObjProp.TimeProp ans = 08-Oct-2003 17:16:08
The TimeProp property of the ContClass object contains the date and time when MATLAB initialized the class. Creating additional instances of the ClassExp class shows that the date string has not changed:
b = ClassExp; b.ObjProp.TimeProp ans = 08-Oct-2003 17:16:08
Because this example uses a value class for the contained object, each instance of the ClassExp has its own copy of the object. For example, suppose you change the value of the TimeProp property on the object contained by ClassExp objectb:
b.ObjProp.TimeProp = datestr(now) ans = 08-Oct-2003 17:22:49
4-10
Now consider the difference in behavior if the contained object is a handle object:
classdef ContClass < handle properties TimeProp = datestr(now); end end
Creating two instances of the ClassExp class shows that MATLAB created an object when it initialized the ContClass and used a copy of the object handle for each instance of the ClassExp class. This means there is one ContClass object and the ObjProp property of each ClassExp object contains a copy of its handle. Create an instance of the ClassExp class and note the time of creation:
a = ClassExp; a.ObjProp.TimeProp ans = 08-Oct-2003 17:46:01
Create a second instance of the ClassExp class. The ObjProp contains the handle of the same object:
b = ClassExp; b.ObjProp.TimeProp ans = 08-Oct-2003 17:46:01
4-11
Because the ObjProp property of object b contains a handle to the same object as the ObjProp property of object a, the value of the TimeProp property has changed on this object as well:
a.ObjProp.TimeProp ans = 08-Oct-2003 17:47:34
See Comparing Handle and Value Classes on page 5-2 for more information on handle and value classes.
4-12
@-Folders
An @-folder is contained by a path folder, but is not itself on the MATLAB path. Place the class definition file inside the @-folder, which can also contain method files. The class definition file must have the same name as the @-folder (without the @-sign) and the class definition (beginning with the classdef key word) must appear in the file before any other code (white space and comments do not constitute code). The name of the class must match the name of the file that contains the class definition.
4-13
You must use an @-folder if you want to use more than one file for your class definition. Methods defined in separate files match the file name to the function name. All files have a .m extension.
Path Folders
You can locate class definition files in folders that are on the MATLAB path. These classes are visible on the path like any ordinary function. Class definitions placed in path folders behave like any ordinary function with respect to precedencethe first occurrence of a name on the MATLAB path takes precedence over all subsequent occurrences. The name of the file must match the name of the class, as specified with the classdef key word. Using a path folder eliminates the need to create a separate @-folder for each class. However, the entire class definition must be contained within a single file. All files have a .m extension.
4-14
precedence and it takes precedence over all class definition files occurring later on the path. For example, consider a path with the following folders, containing the files indicated:
fldr1/foo.m fldr2/foo.m fldr3/@foo/foo.m fldr4/@foo/bar.m fldr5/foo.m % % % % % defines defines defines defines defines class foo function foo class foo method bar class foo
The MATLAB language applies the logic in the following list to determine which version of foo to call: Class fldr1/foo.m takes precedence over the class fldr3/@foo because it is before fldr3/@foo on the path. Class fldr3/@foo takes precedence over function fldr2/foo.m because it is a class in an @-folder and fldr2/foo.m is not a class (@-folder classes take precedence over functions). Function fldr2/foo.m takes precedence over class fldr5/foo.m because it comes before class fldr5/foo.m on the path and because class fldr5/foo.m is not in an @-folder. Classes not defined in @-folder abide by path order with respect to functions. Class fldr3/@foo takes precedence over class fldr4/@foo; therefore, the method bar is not recognized as part of the foo class (which is defined only by fldr3/@foo). If fldr3/@foo/foo.m does not contain a classdef keyword (i.e., it is a MATLAB class prior to Version 7.6), then fldr4/@foo/bar.m becomes a method of the foo class defined in fldr3/@foo.
4-15
Note that for backward compatibility, classes defined in @-folders always take precedence over functions and scripts having the same name, even those that come before them on the path.
4-16
The ? operator combined with a class name creates a meta.class object. This syntax enables you to create a meta.class object without requiring you to construct an actual instance of the class. MATLAB built-in classes are always inferior to user-defined classes and should not be used in this list. The built-in classes include: double, single, char, logical, int64, uint64, int32, uint32, int16, uint16, int8, uint8, cell, struct, and function_handle.
Dominant Class
MATLAB uses class dominance when evaluating expressions involving objects of more than one class. The dominant class determines: The methods of which class MATLAB calls when more than one class defines methods with the same names. The class of arrays that are formed by combining objects of different classes, assuming MATLAB can convert the inferior objects to the dominant class. See Concatenating Objects of Different Classes on page 8-13 for more information on creating object arrays.
4-17
More Information
See Determining Which Method Is Invoked on page 7-8 for more on how the MATLAB classes dispatch when evaluating expressions containing objects. See Class Precedence and MATLAB Path on page 4-14 for information on how the location of a class definition on the MATLAB path determines its precedence. See Working with Meta-Classes on page 14-2 for information on meta-class objects.
No Attribute Inheritance
Subclasses do not inherit a superclass InferiorClasses attribute. Only instances of the classes specified in the subclass InferiorClasses attribute are inferior to subclass objects.
4-18
Package Folders
Packages are special folders that can contain class folders, function and class definition files, and other packages. Packages define a scope (sometimes called a namespace) for the contents of the package folder. This means function and class names need to be unique only within the package. Using a package provides a means to organize classes and functions and to select names for these components that other packages can reuse. Note Packages are not supported for classes created prior to MATLAB Version 7.6 (i.e., classes that do not use classdef). Package folders always begin with the + character. For example,
+mypack +mypack/pkfcn.m % a package function +mypack/@myClass % class folder in a package
The top-level package folders parent folder must be on the MATLAB path.
4-19
EventData
PropertyEvent
listener
proplistener
Note that definitions do not use the package prefix. For example, the function definition line of the pkfcn.m function would include only the function name:
function z = pkfcn(x,y)
Similarly, a package class would be defined with only the class name:
classdef myClass
Calling class methods does not require the package name because you have an instance of the class:
obj.myMethod(arg) or myMethod(obj,arg)
4-20
If mypack.myfirstclass has a method called myfcn, it is called as any method call on an object:
obj = mypack.myfirstclass; myfcn(obj,arg);
If mypack.myfirstclass has a property called MyProp, it can be assigned using dot notation and the object:
obj = mypack.myfirstclass; obj.MyProp = some_value;
4-21
A call to which foo returns the path to the executable class constructor:
>> which foo fldr2/@foo/foo.m
A function and a package can have the same name. However, a package name by itself is not an identifier so if a redundant name occurs alone, it identifies the function. Executing a package name alone returns an error.
4-22
In cases where a path folder contains both package and class folders with the same name, the class static method takes precedence over the package method:
fldr1/@foo/bar.m % bar is a static method of class foo fldr1/+foo/bar.m % bar is a function in package foo
4-23
Importing Classes
In this section... Related Information on page 4-24 Syntax for Importing Classes on page 4-24
Related Information
See Scoping Classes with Packages on page 4-19 for information about packages.
Note that you do not need to reference the package name (pkg) once you have imported the class (cls1). You can also import all classes in a package using the syntax pkg.*, where * indicates all classes in the package. For example,
function myFunc import pkg.* obj1 = cls1(arg,...); % call pkg.cls1 constructor obj2 = cls2(arg,...); % call pkg.cls2 constructor a = pkgFunction(); % call package function named pkgFunction end
4-24
Importing Classes
function myFunc import pkg.pkfcn pkfcn(arg,...); % call imported package function end
A call to timedata finds the package function, not the class method because MATLAB applies the import and finds pkg.timedata first. Do not use a package in cases where you have name conflicts and plan to import the package.
4-25
4-26
5
Value or Handle Class Which to Use
Comparing Handle and Value Classes on page 5-2 Which Kind of Class to Use on page 5-9 The Handle Superclass on page 5-11 Finding Handle Objects and Properties on page 5-19 Implementing a Set/Get Interface for Properties on page 5-21 Controlling the Number of Instances on page 5-25
Basic Difference
A value class constructor returns an instance that is associated with the variable to which it is assigned. If you reassign this variable, MATLAB creates a copy of the original object. If you pass this variable to a function, the function must return the modified object. A handle class constructor returns a handle object that is a references to the object created. You can assign the handle object to multiple variables or pass it to functions without causing MATLAB to make a copy of the original object. A function that modifies a handle object passed as an input argument does not need to return the object. Note All handle classes must subclass the abstract handle class. compares handle and value object behavior when used as arguments to functions.
5-2
contains information for a phone book entry. Multiple application programs can access a particular phone book entry, but there can be only one set of underlying data. The reference behavior of handles enables these classes to support features like events, listeners, and dynamic properties. Use value classes to represent entities that do not need to be unique, like numeric values. For example, use a value class to implement a polynomial data type. You can copy a polynomial object and then modify its coefficients to make a different polynomial without affecting the original polynomial. Which Kind of Class to Use on page 5-9 describes how to select the kind of class to use for your application.
MATLAB copies the value of a to b, which results in two independent versions of the original object. This behavior is typical of MATLAB numeric classes. Handle Graphics classes return a handle to the object created. A handle is a variable that references an instance of a class. If you copy the handle, you have another variable that refers to the same object. There is still only one version of the object data. For example, if you create a Handle Graphics line object and copy its handle to another variable, you can set the properties of the same line using either copy of the handle.
5-3
x = 1:10; y = sin(x); h1 = line(x,y); h2 = h1; >>set(h2,'Color','red') % line is red >>set(h1,'Color','green') % line is green >>delete(h2) >>set(h1,'Color','blue') ??? Error using ==> set Invalid handle object.
Note also, if you delete one handle, all copies are now invalid because you have deleted the single object that all copies point to.
Value Classes
MATLAB associates objects of value classes with the variables to which you assign them. When you copy a value object, MATLAB also copies the data contained by the object. The new object is independent of changes to the original object. Instances behave like standard MATLAB numeric and struct classes. Each property behaves essentially like a MATLAB array See Memory Allocation for Arrays for more information.
5-4
end
Handle Classes
Objects of handle classes use a handle to reference objects of the class. A handle is a variable that identifies an instance of a class. When you copy a handle object, MATLAB copies the handle, but not the data stored in the object properties. The copy refers to the same data as the original handle. If you change a property value on the original object, the copied object reflects the same change. All handle classes are subclasses of the abstract handle class. In addition to providing handle copy semantics, deriving from the handle class enables your class to: Inherit a number of useful methods (Handle Class Methods on page 5-12) Define events and listeners (Defining Events and Listeners Syntax and Techniques on page 9-15) Define dynamic properties (Dynamic Properties Adding Properties to an Instance on page 6-21) Implement Handle Graphics type set and get methods (Implementing a Set/Get Interface for Properties on page 5-21)
5-5
end
See The Handle Superclass on page 5-11 for more information on the handle class and its methods.
Create a subclass of the employee class for engineer employees, which is also a handle class. You do not need to specify handle as a superclass in the classdef:
classdef engineer < employee ... end
5-6
properties Name = '' Department = ''; end methods function e = employee(name,dept) e.Name = name; e.Department = dept; end % employee function transfer(obj,newDepartment) obj.Department = newDepartment; end % transfer end end
The transfer method in the previous code changes the employees department (the Department property of an employee object). In the following statements, e2 is a copy of the handle object e. Notice that when you change the Department property of object e, the property value also changes in object e2.
e = employee('Fred Smith','QE'); e2 = e; % Copy handle object transfer(e,'Engineering') e2.Department ans = Engineering
The variable e2 is an alias for e and refers to the same property data storage as e.
5-7
When you call transfer, assign the output argument to create the modified object.
e = transfer(e,'Engineering');
In a value class, the transfer method does not affect the variable e2, which is a different employee object. In this example, having two independent copies of objects representing the same employee is not a good design. Hence, implement the employee class as a handle class.
Deleting Handles
You can destroy handle objects before they become unreachable by explicitly calling the delete function. Deleting the handle of a handle class object makes all handles invalid. For example:
delete(e2) e.Department ??? Invalid or deleted object.
Calling the delete function on a handle object invokes the destructor function or functions for that object. See Handle Class Delete Methods on page 5-15 for more information.
5-8
A copy of a graphics object (such as a line) has a different position in its parents list of children than the object from which it was copied. Therefore, the two objects are not identical. Nodes in lists or trees having specific connectivity to other nodesno two nodes can have the same connectivity.
5-9
The class represents physical and unique objects like serial ports or printers, in which the entity or state cannot exist in a MATLAB variable. However, a handle to such entity can be a variable. The class defines events and notifies listeners when an event occurs (notify is a handle class method). The class creates listeners by calling the handle class addlistener method. The class subclasses the dynamicprops class (a subclass of handle) so that instances can define dynamic properties. The class subclasses the hgsetget class (a subclass of handle) so that it can implement a Handle Graphics style set/get interface. You want to create a singleton class or a class in which you track the number of instances from within the constructor. MATLAB software never creates a unique handle without calling the class constructor. A copy of a handle object is not unique because both original and copy reference the same data.
5-10
Handle Subclasses
There are two subclasses of the handle class that provide additional features when you derive your class from these subclasses: hgsetget Provides set and get methods that enable you to implement a Handle Graphics style interface. See Implementing a Set/Get Interface for Properties on page 5-21 for information on subclassing hgsetget. dynamicprops Provides the ability to define instance properties. See Dynamic Properties Adding Properties to an Instance on page 6-21 for information on subclassing dynamicprops. Deriving from subclasses of the handle class means that your class is a handle class. It inherits all the handle class methods, plus the special features provided by these subclasses.
5-11
Defining Events and Listeners Syntax and Techniques on page 9-15 provides information on how to use the notify and addlistener methods, which are related to the use of events. Creating Subclasses Syntax and Techniques on page 10-7 provides general information on defining subclasses.
Relational Methods
function function function function function function TF TF TF TF TF TF = = = = = = eq(H1,H2) ne(H1,H2) lt(H1,H2) le(H1,H2) gt(H1,H2) ge(H1,H2)
The handle class overloads these functions with implementations that allow for equality tests and sorting on handles. For each pair of input arrays, these functions return a logical array of the same size. Each element is an
5-12
element-wise equality or comparison test result. The input arrays must be the same size or one (or both) can be scalar. The method performs scalar expansion as required.
5-13
Determine the difference between the graphics object handle (stored in the UiHandle property) and the handle class object, h. Use ishandle to test the validity of Handle Graphics object handles:
% h is a handle object >> isa(h,'handle') ans = 1 % The uicontrol object handle is not a handle object >> isa(h.UiHandle,'handle') ans = 0 % The button object is not a graphics object >> ishandle(h) ans = 0 % The uicontrol is a graphics object handle >> ishandle(h.UiHandle) ans = 1
If you close the figure, the ishandle function determines that the Handle Graphics handle is not valid:
>> close >> ishandle(h.UiHandle) ans = 0 h is still of class handle and is still a valid handle object: >> isa(h,'handle') ans = 1
5-14
5-15
where h is a scalar handle. For example, close a file that you have opened for writing in your objects delete method. This function calls fclose on a file identifier that the objects FileID property stores:
function delete(obj) fclose(obj.FileID); end
Using Objects to Write Data to a File on page 2-18 presents an example that uses this delete method.
Object Lifecycle
The MATLAB runtime invokes the delete method only when the lifecycle of an object ends. The lifecycle of an object ends when the object is: No longer referenced anywhere Explicitly deleted by calling delete on the handle Inside a Function. The lifecycle of an object referenced by a local variable or input argument exists from the time the variable is assigned until the time it is reassigned, cleared, or no longer referenced within that function or any handle array. A variable goes out of scope when you explicitly cleared it or when its function ends. When a variable goes out of scope, if its value belongs to a class that defines a delete method, MATLAB calls that method. MATLAB defines no ordering among variables in a function. Do not assume that MATLAB destroys one value before another value when the same function contains both values.
5-16
classes and working up the hierarchy to the most general base classes MATLAB invokes the delete methods of superclasses at the same level in the hierarchy as the order specified in the class definition. For example, the following class definition specifies supclass1 before supclass2 so MATLAB calls the delete function of supclass1 before the delete function of supclass2.
classdef myClass < supclass1 & supclass2
Superclass delete methods cannot call methods or access properties belonging to a subclass. After calling each delete method, MATLAB destroys the property values belonging exclusively to the class whose method was called. The destruction of property values that contain other handle objects causes MATLAB to call the delete methods for those objects.
5-17
of the delete method of only the direct class of the object. Therefore, a private delete method of a superclass does not prevent the destruction of an object of a subclass. This behavior differs from the normal behavior of an overridden method. MATLAB executes each delete method of each base class of an object upon destruction, even if that delete method is not public. Declaring a private delete method probably makes sense only for sealed classes (Sealed attribute set to true). If you design a class that you will subclass, declaring its delete method to be protected prevents objects of all subclasses from destruction by a call to delete from outside the class. Even when you declare a delete method to be protected, MATLAB calls the delete method of each superclass when destroying the object.
5-18
The findobj method returns an array of handles matching the conditions specified.
The findprop method returns the meta.property object associated with the PropertyName property defined by the class of h. The property can also be a dynamic property created by the addprop method of the dynamicprops class. You can use the returned meta.property object to obtain information about the property, such as querying the settings of any of its attributes. For example, the following statements determine that the setting of the AccountStatus propertys Dependent attribute is false.
ba = BankAccount(007,50,'open'); mp = findprop(ba,'AccountStatus'); % get meta.property object mp.Dependent ans = 0
5-19
5-20
If you do not specify property names, get returns a struct array in which each element corresponds to the element in H. Each field in the struct corresponds to a property defined by the class of H. The value of each field is the value of the corresponding property. If you specify prop as a char array, then MATLAB interprets it as a property name. get returns the value of that property if H is scalar, or returns a cell array of property values if H is an array of handles. The cell array is always a column vector regardless of the shape of H. If prop is a
5-21
cell array of string property values, then get returns a cell array of values where each row in the cell corresponds to an element in H and each column in the cell corresponds to an element in prop.
If you do not specify property values, set returns a cell array of possible values for each requested property when the property value is a finite enumeration of possible values. If you specify only H, set returns a struct with one field for each property in the class of H. Each field contains either an empty cell array or a cell array of possible property values (if such a finite set exists). If you specify prop as a string containing a property name, then set returns either a cell array of possible values or an empty cell. If you specify prop as a cell array of property names, then set returns a cell column vector. Each cell corresponds to a property in prop and each cell value is a cell array of possible values, or empty if there is no finite enumeration of possible values. You can also pass property-value pairs to set using cell arrays and structures as described for the builtin set function.
Subclassing hgsetget
This example creates a class with the set/get interface and illustrates the behavior of the inherited methods:
classdef MyAccount < hgsetget % subclass hgsetget properties AccountNumber AccountBalance = 0; AccountStatus end % properties
5-22
methods function obj = MyAccount(actnum,intamount,status) obj.AccountNumber = actnum; obj.AccountBalance = intamount; obj.AccountStatus = status; end % MyAccount function obj = set.AccountStatus(obj,val) if ~(strcmpi(val,'open') ||... strcmpi(val,'deficit') ||... strcmpi(val,'frozen')) error('Invalid value for AccountStatus ') end obj.AccountStatus = val; end % set.AccountStatus end % methods end % classdef
You can query the value of any object property using the inherited get method:
get(h,'AccountBalance') ans = 500
You can set the value of any property using the inherited set method:
set(h,'AccountStatus','frozen')
MATLAB calls the property set function (set.AccountStatus) when you use the set method:
set(h,'AccountStatus','closed') ??? Error using ==> MyAccount.MyAccount>MyAccount.set.AccountStatus at 19 Invalid value for AccountStatus
5-23
Similarly, you can list the setable properties of the object using set:
set(h) AccountNumber: {} AccountBalance: {} AccountStatus: {}
5-24
The getInstance static method returns a handle to the object created, which the class stores in a persistent variable. getInstance creates an instance only the first time called in a session or when the object becomes invalid. For example:
5-25
sobj = SingleInstance.getInstance sobj = SingleInstance handle with no properties. Methods, Events, Superclasses
As long as sobj exists as a valid handle, calling getInstance returns a handle to the same object. If you delete sobj, then calling getInstance creates an object and returns the handle.
delete(sobj) isvalid(sobj) ans = 0 sobj = SingleInstance.getInstance; isvalid(sobj) ans = 1
5-26
6
Properties Storing Class Data
How to Use Properties on page 6-2 Defining Properties on page 6-5 Property Attributes on page 6-8 Property Set and Get Access Methods on page 6-12 Dynamic Properties Adding Properties to an Instance on page 6-21
6-2
Types of Properties
There are two types of properties: Stored properties Use memory and are part of the object Dependent properties No allocated memory and the get access method calculates the value when queried
6-3
Property Set and Get Access Methods on page 6-12 provides information on defining property access methods.
6-4
Defining Properties
Defining Properties
In this section... Property Definition Block on page 6-5 Accessing Property Values on page 6-6 Inheritance of Properties on page 6-6 Specifying Property Attributes on page 6-7
6-5
When you access a property, MATLAB performs any operations that the property requires. For example, executing a property set or get access method and triggering property access events. See Implementing a Set/Get Interface for Properties on page 5-21 for information on how to define set and get methods for properties.
Inheritance of Properties
When you derive one class from another class, the derived (subclass) class inherits all the properties of the superclass. In general, subclasses define only properties that are unique to that particular class. Superclasses define properties that more than one subclass use.
6-6
Defining Properties
properties Coefficients = [0 0 1]; end properties (SetAccess = private) IndependentVar Order = 0; end
These properties (and any others placed in this block) have private set access
6-7
Property Attributes
Table of Property Attributes
All properties support the attributes listed in the following table. Attributes enable you to modify the behavior of properties. Attribute values apply to all properties defined within the properties block that specifies the nondefault values. Attribute Name
AbortSet
Description If true, and this property belongs to a handle class, then MATLAB does not set the property value if the new value is the same as the current value. This approach prevents the triggering of property PreSet and PostSet events. If true, the property has no implementation, but a concrete subclass must redefine this property without Abstract being set to true. Abstract properties cannot define set or get access methods. See Property Set and Get Access Methods on page 6-12. Abstract properties cannot define initial values. See Assigning a Default Value on page 6-6. All subclasses must specify the same values as the superclass for the property SetAccess and GetAccess attributes. Abstract=true use with the class attribute Sealed=false (the default).
Abstract
6-8
Property Attributes
Class
char
Description
public unrestricted access protected access from class or derived
default = public
classes
private access by class members only
Use Access to set both SetAccess and GetAccess to the same value. Query the values of SetAccess and GetAccess directly (not Access).
Constant
Set to true if you want only one value for this property in all instances of the class: Subclasses inherit constant properties, but cannot change them. Constant properties cannot be Dependent. SetAccess is ignored. See for more information.
Dependent
If false, property value stored in object. If true, property value is not stored in object. The set and get functions cannot access the property by indexing into the object using the property name. MATLAB does not display in the command window the names and values of Dependent properties that do not define a get method (scalar object display only). See Dependent Properties on page 2-27, Property Get Methods on page
6-9
(Continued) Attribute Name Class Description 6-16, Avoiding Property Initialization Order Dependency on page 11-23
GetAccess
derived classes
private access by class members only
MATLAB does not display in the command window the names and values of properties having protected or private GetAccess or properties whose Hidden attribute is true.
GetObservable
If true, and it is a handle class property, then you can create listeners for access to this property. The listeners are called whenever property values are queried. See Property-Set and Query Events on page 9-12 Determines whether the property should be shown in a property list (e.g., Property Inspector, call to set or get, etc.). MATLAB does not display in the command window the names and values of properties whose Hidden attribute is true or properties having protected or private GetAccess.
Hidden
SetAccess
derived classes
private access by class members only immutable property can be set only in the constructor.
6-10
Property Attributes
Description If true, and it is a handle class property, then you can create listeners for access to this property. The listeners are called whenever property values are modified. See Property-Set and Query Events on page 9-12 If true, property value is not saved when object is saved to a file. See The Save and Load Process on page 11-2 for more about saving objects.
Transient
6-11
Impose value range restrictions (Restricting Properties to Specific Values on page 2-25) Check for proper types and dimensions Provide error handling
Execute code before returning the current values of properties to perform actions such as: Calculate the value of properties that do not store values (for an example, see Dependent Properties Values Not Stored on page 6-16) Change the value of other properties Trigger events (for an example, see Defining and Triggering an Event on page 9-4)
Property access methods execute automatically whenever you query or set the corresponding property values.
6-12
6-13
Define property access methods in a methods block that specifies no attributes. You cannot call these methods, MATLAB calls them when any code accesses the properties. Therefore, property access methods do not appear in the list of class methods returned by the methods command and are not included in the meta.class objects Methods property. However, the meta.property objects SetMethod property contains a function handle to the propertys set method and the GetMethod property contains a function handle to the propertys get method. For example, if the class myClass defines a set function for its Text property, you can obtain a function handle to this method from the meta.class object:
m = ?myClass; m.Properties{1}.SetMethod % Assuming Text is the first property in the cell array ans = @\mydir\@myClass\myClass.m>myClass.set.Text % This is a function handle
The meta.class object (m) contains meta.property objects corresponding to each class property in its Properties property. This example assumes that the Text property corresponds to the first meta.property object in the cell array of meta.property objects. The order of the class properties in the meta.class Properties property is the same as the order in which the class definition defines the properties. Working with Meta-Classes on page 14-2 provides more information on using meta-classes. Function Handles discusses the use of function handles.
Here obj is the object whose property is being assigned a value and value is the new value that is assigned to the property.
6-14
Value class set functions must return the object with the new value for the property assigned. Value classes replace the object whose property is being assigned with the object returned by the set method. Handle classes do not need to return the modified object.
methods % No method attributes function set.PropertyName(obj,value) % Handle class end
The property set method can perform actions like error checking on the input value before taking whatever action is necessary to store the new property value.
function obj = set.PropertyName(obj,value) if ~(value > 0) error('Property value must be positive') else obj.PropertyName = value; end end
See Restricting Properties to Specific Values on page 2-25 for an example of a property set method.
6-15
It is possible for a set method from one property to assign values to other properties of the object. However, assignments made from property set methods cause the execution of any set methods defined for those properties. When assigning a property value, the calling functions copy of the object that has been passed to the set method reflects the changed value. Therefore, an assignment to even a single property is able to affect the whole object. This behavior enables a set method to change other properties in the object as well as its designated property. For example, a graphics window object can have a Units property and a Size property. Changing the Units property can also require a change to the values of the Size property to reflect the new units.
Property get methods have the following syntax, where PropertyName is the name of the property. The function must return the property value.
methods % No method attributes function value = get.PropertyName(obj) end
end
Now the get method for the PropertyName property determines the value of that property and assigns it to the object from within the method:
6-16
The get method calls a function or static method calculateValue to calculate the property value and returns value to the code accessing the property. The property get method can take whatever action is necessary within the method to produce the output value. Dependent Properties on page 2-27 provide an example of a property get method.
There is no memory wasted by storing both old and new property values, and code that accesses OldPropName continues to work as expected.
6-17
This example uses the MaxValue property to return a value that it calculates only when queried. For this application, define the MaxValue property as dependent and private:
properties (Dependent, SetAccess = private) MaxValue end
6-18
PostSet Triggered after assigning the new property value within the set method Events and Listeners Concepts on page 9-9 provides general information about events and listeners. Creating Property Listeners on page 9-23 provides information about using property events. Implementing the PostSet Property Event and Listener on page 9-43 shows an example of a property listener. Responding to a Button Click on page 9-6 is another example that uses property events.
6-19
6-20
6-21
Listen for dynamic property events (see Responding to Dynamic-Property Events on page 6-23) Access dynamic property values from object arrays, with restricted syntax (see Object Arrays with Dynamic Properties on page 8-10)
where:
P is an array of meta.DynamicProperty objects H is an array of handles PropertyName is the name of the dynamic property you are adding to each
object
You can remove the dynamic property by deleting its meta.DynamicProperty object:
delete(P);
The property attributes Constant and Abstract have no meaning for dynamic properties and setting the value of these attributes to true has no effect.
6-22
store location data for your particular layout scheme and you want to avoid creating a map or hash table to maintain this information separately. Assuming the button class is a subclass of dynamicprops, you could add a dynamic property to store your layout data. Here is a simple class to create a uicontrol button:
classdef button < dynamicprops properties UiHandle end methods function obj = button(pos) obj.UiHandle = uicontrol('Position',pos); end end end
Create an instance of the button class, add a dynamic property, and set its value:
b1 = button([20 40 80 20]); % button class uses HG-type position layout b1.addprop('myCoord'); % Add a dynamic property b1.myCoord = [2,3]; % Set the property value
You can access the dynamic property just like any other property, but only on the instance on which you defined it:
>> b1.myCoord ans = 2 3
6-23
ObjectBeingDestroyed Inherited from the handle class. PropertyAdded Triggered when you add a dynamic property to an object derived from the dynamicprops class. PropertyRemoved Triggered when you delete the meta.DynamicProperty object associated with the dynamic property. Suppose you define a button object, as described in the previous section:
b2 = button([20 40 80 20]);
Create a function to attach listeners to the button object, b2, and a listener callback function:
function listenDynoEvent(obj) addlistener(obj,'PropertyAdded',@eventPR); addlistener(obj,'PropertyRemoved',@eventPR); function eventPR(src,evnt) mc = metaclass(src); fprintf(1,'%s %s \n',mc.Name,'object') fprintf(1,'%s %s \n','Event triggered:',evnt.EventName) end end
The listener callback function, eventPR, executes and displays the object class and event name:
button object Event triggered: PropertyAdded
6-24
Obtain the meta.DynamicProperty object for a dynamic property using the handle findprop method. Use findprop if you do not have the object returned by addprop:
mp = findprop(b2,'myCoord');
6-25
Here are the steps for creating a property access method: Define a function that implements the desired operations you want to perform before the property set or get occurs. These methods must have the following signatures: mySet(obj,val) or val = myGet(obj) Obtain the dynamic propertys corresponding meta.DynamicProperty object. Assign a function handle pointing to your set or get property function to the meta.DynamicProperty objects GetMethod or SetMethod property. This function does not need to be a method of the class and you cannot use a naming scheme like set.PropertyName. Instead, use any valid function name. Suppose you want to create a property set function for the button class dynamic property myCoord created previously. Write the function as follows:
function set_myCoord(obj,val) if end obj.myCoord = val; % set property value end ~(length(val) == 2) % require two values error('myCoords require two values ')
Because button is a handle class, the property set function does not need to return the object as an output argument. You simply assign the value to the property if the value is value is valid. Use the handle class method findprop to get the meta.DynamicProperty object:
mb1 = b1.findprop('myCoord'); mb1.SetMethod = @set_myCoord;
The property set function is now called whenever you set this property:
b1.myCoord = [1 2 3] % length must be two ??? Error using ==> set_myCoord at 3 myCoords require two values
6-26
6-27
6-28
7
Methods Defining Class Operations
Class Methods on page 7-2 Method Attributes on page 7-4 Ordinary Methods on page 7-6 Class Constructor Methods on page 7-15 Static Methods on page 7-24 Overloading Functions for Your Class on page 7-26 Object Precedence in Expressions Using Operators on page 7-29 Class Methods for Graphics Callbacks on page 7-31
Class Methods
What Are Methods
Methods are functions that implement the operations performed on objects of a class. Methods, along with other class members support the concept of encapsulationclass instances contain data in properties and class methods operate on that data. This allows the internal workings of classes to be hidden from code outside of the class, and thereby enabling the class implementation to change without affecting code that is external to the class. Methods have access to private members of their class including other methods and properties. This enables you to hide data and create special interfaces that must be used to access the data stored in objects. See Methods That Modify Default Behavior on page 15-2 for a discussion of how to create classes that modify standard MATLAB behavior. See Class Folders on page 3-2 for information on the use of @ and path directors and packages to organize your class files. See Methods In Separate Files on page 3-14 for the syntax to use when defining classes in more than one file.
Kinds of Methods
There are specialized kinds of methods that perform certain functions or behave in particular ways: Ordinary methods are functions that act on one or more objects and return some new object or some computed value. These methods are like ordinary MATLAB functions that cannot modify input arguments. Ordinary methods enable classes to implement arithmetic operators and computational functions. These methods require an object of the class on which to operate. See Ordinary Methods on page 7-6. Constructor methods are specialized methods that create objects of the class. A constructor method must have the same name as the class and typically initializes property values with data obtained from input
7-2
Class Methods
arguments. The class constructor method must return the object it creates. See Class Constructor Methods on page 7-15 Destructor methods are called automatically when the object is destroyed, for example if you call delete(object) or there are no longer any references to the object. See Handle Class Delete Methods on page 5-15 Property access methods enable a class to define code to execute whenever a property value is queried or set. See Property Access Methods on page 6-12 Static methods are functions that are associated with a class, but do not necessarily operate on class objects. These methods do not require an instance of the class to be referenced during invocation of the method, but typically perform operations in a way specific to the class. See Static Methods on page 7-24 Conversion methods are overloaded constructor methods from other classes that enable your class to convert its own objects to the class of the overloaded constructor. For example, if your class implements a double method, then this method is called instead of the double class constructor to convert your class object to a MATLAB double object. See Converting Objects to Another Class on page 15-11 for more information. Abstract methods serve to define a class that cannot be instantiated itself, but serves as a way to define a common interface used by a number of subclasses. Classes that contain abstract methods are often referred to as interfaces. See Abstract Classes and Interfaces on page 10-50 for more information and examples.
7-3
Method Attributes
Table of Method Attributes
All methods support the attributes listed in the following table. Attributes enable you to modify the behavior of methods. For example, you can prevent access to a method from outside the class or enable the method to be invoked without a class instance. Attribute values apply to all methods defined within the methods block that specifies the nondefault values.
methods (attribute1=value1,attribute2=value2,...) ... end
Attribute Name
Abstract
Class
logical
Description If true, the method has no implementation. The method has a syntax line that can include arguments, which subclasses use when implementing the method: Subclasses are not required to define the same number of input and output arguments. However, subclasses generally use the same signature when implementing their version of the method. The method can have comments after the function line. The method does not contain function or end keywords, only the function syntax (e.g., [a,b] = myMethod(x,y))
Default=false
Access
Determines what code can call this method: public Unrestricted access protected Access from methods in class or subclasses private Access by class methods only (not from subclasses)
7-4
Method Attributes
Class
logical
Description When false, the method name shows in the list of methods displayed using the methods or methodsview commands. If set to true, the method name is not included in these listings. If true, the method cannot be redefined in a subclass. Attempting to define a method with the same name in a subclass causes an error. Set to true to define a method that does not depend on an object of the class and does not require an object argument. You must use the class name to call the method:
classname.methodname
Default=false
Sealed
logical
Default=false
Static logical
Default=false
7-5
Ordinary Methods
In this section... Defining Methods on page 7-6 Determining Which Method Is Invoked on page 7-8 Specifying Precedence on page 7-12 Controlling Access to Methods on page 7-12 Invoking Superclass Methods in Subclass Methods on page 7-13 Invoking Built-In Methods on page 7-14
Defining Methods
You can specify methods: Inside of a class definition block In a separate file in the class @-folder
7-6
Ordinary Methods
Note Nonstatic methods must include an explicit object variable in the function definition. The MATLAB language does not support an implicit reference in the method function definition. Either of the following statements is correct syntax for calling a method where obj is an object of the class defining the compute method:
obj.compute(inc) compute(obj,inc)
See also Dot Notation vs. Function Notation on page 7-9. Method attributes apply only to that particular methods block, which is terminated by the end statement.
Do not use methods blocks in the separate files. Define the method as a function. Using the example above, the file testdata.m, must contain the definition of the testdata function. Note that the signatures must match.
function tdata = testdata(myClass_object,argument2,argument3) ... end
7-7
The following limitations apply to methods defined in separate files: If you want to specify attributes for a method defined in a separate file, you must declare this method in a methods block (specifying attribute values) within the classdef block. The syntax declared in the methods block (if used) must match the methods function line. The separate file must be in the class @-folder. The constructor method must be defined within the classdef block and, therefore, cannot be in a separate file. (See Class Constructor Methods on page 7-15 for information on this method.) Set and get property access methods must be defined within the classdef block and, therefore, cannot be in separate files. (See Property Set and Get Access Methods on page 6-12 for information on these methods.)
Dominant Argument
The dominant argument in a methods argument list determines which version of the method or function that the MATLAB runtime calls. Dominance is determined by the relative precedences of the classes of the arguments. In general, user-defined classes take precedence over built-in MATLAB classes. Therefore, the left most argument determines which method to call. However, user-defined classes can specify the relative dominance of specific classes.
7-8
Ordinary Methods
For example, suppose classA defines classB as inferior and suppose both classes define a method called combine. Calling the method with an object of classB and classA:
combine(B,A)
actually calls the combine method of classA because A is the dominant argument. See Specifying Precedence on page 7-12 for information on how to define class precedence.
However, in certain cases, the results for dot notation can differ with respect to how MATLAB dispatching works: If there is an overloaded subsref, it is invoked whenever using dot-notation. That is, the statement is first tested to see if it is subscripted assignment. If there is no overloaded subsref, then setColor must be a method of X. An ordinary function or a class constructor is never called using this notation. Only the argument X (to the left of the dot) is used for dispatching. No other arguments, even if dominant, are considered. Therefore dot notation can call only methods of X; methods of other argument are never called. A Case Where the Result is Different. Here is an example of a case where dot and function notation can give different results. Suppose you have the following classes:
7-9
classA defines a method called methodA that requires an object of classB as one of its arguments classB defines classA as inferior to classB
classdef classB (InferiorClasses = {?classA}) ... end
The methodA method is defined with two input arguments, one of which is an object of classB:
classdef classA methods function methodA(obj,obj_classB) ... end end classB does not define a method with the same name as methodA. Therefore,
the following syntax causes the MATLAB runtime to search the path for a function with the same name as methodA because the second argument is an object of a dominant class. If a function with that name exists on the path, then MATLAB attempts to call this function instead of the method of classA and most likely returns a syntax error.
obj = classA(...); methodA(obj,obj_classB)
Dot notation is stricter in its behavior. For example, this call to methodA:
obj = classA(...); obj.methodA(obj_classB)
7-10
Ordinary Methods
The expression must evaluate to a string that is the name of a property or a method. For example, the following statements are equivalent:
obj.Property1 obj.('Property1')
In this case, obj is an object of a class that defines a property called Property1. Therefore, you can pass a string variable in the parentheses to reference to property:
propName = 'Property1'; obj.(propName)
You can call a method and pass input arguments to the method using another set of parentheses:
obj.(expression)(arg1,arg2,...)
Using this notation, you can make dynamic references to properties and methods in the same way you can create dynamic references to the fields of structs (see Creating Field Names Dynamically for information on MATLAB structures). As an example, suppose an object has methods corresponding to each day of the week and these methods have the same names as the days of the week (Monday, Tuesday, and so on). Also, the methods take as string input arguments, the current day of the month (i.e., the date). Now suppose you write a function in which you want to call the correct method for the current day. You can do this using an expression created with the date and datestr functions:
obj.(datestr(date,'dddd'))(datestr(date,'dd'))
The expression datestr(date,'dddd') returns the current day as a string. For example:
datestr(date,'dddd') ans = Tuesday
7-11
The expression datestr(date,'dd') returns the current date as a string. For example:
datestr(date,'dd') ans = 11
Therefore, the expression using dot-parentheses (called on Tuesday the 11th) is the equivalent of:
obj.Tuesday('11')
Specifying Precedence
Specifying Class Precedence on page 4-17 provides information on how you can specify the relative precedence of user-define classes.
7-12
Ordinary Methods
For example, the following disp method is defined for a Stock class that is derived from an Asset class. The method first calls the Asset class disp method, passing the Stock object so that the Asset components of the Stock object can be displayed. After the Asset disp method returns, the Stock disp method displays the two Stock properties:
classdef Stock < Asset methods function disp(s) disp@Asset(s) % Call base class disp method first fprintf(1,'Number of shares: %g\nShare price: %3.2f\n',... s.NumShares,s.SharePrice); end % disp end end
See The DocStock disp Method on page 17-10 for more information on this example.
Limitations of Use
The following restrictions apply to calling superclass methods. You can use this notation only within: A method having the same name as the superclass method you are invoking A class that is a subclass of the superclass whose method you are invoking
7-13
7-14
7-15
If a class does not define a constructor, MATLAB supplies a constructor that takes no arguments and returns a scalar object whose properties are initialized to empty or the values specified as defaults in the property definitions. The constructor supplied by MATLAB also calls all superclass constructors with no arguments. If you create a class constructor, you should implement class constructors so that they can be called with no input arguments, in addition to whatever arguments are normally required See Supporting the No Input Argument Case on page 7-18 and Basic Structure of Constructor Methods on page 7-22. Constructors must always return objects of their own class. A superclass constructor cannot return an object of a subclass. Calls to superclass constructors cannot be conditional. This means superclass construction calls cannot be placed in loops, conditions, switches, try/catch, or nested functions. See Make No Conditional Calls to Superclass Constructors on page 7-19 for more information. You can restrict access to constructors using method attributes, as with any method.
Related Information
See Creating Object Arrays on page 8-3 for information on constructing arrays of objects. See Constructor Calling Sequence on page 12-11 for information specific to constructing enumerations.
7-16
Referencing Superclasses from Subclasses on page 10-7 Constructor Arguments and Object Initialization on page 10-9
end
You can call other class methods from the constructor because the object is already initialized. The constructor also creates an object whose properties have their default valueseither empty ([]) or the default value specified in the property definition block. See Property Definition Block on page 6-5 for a description of this syntax and see Defining Default Values on page 3-9 for a discussion of how best to define property values. For example, the following code calls the class method CalculateValue to assign the value of the property Value.
function obj = myClass(a,b,c) obj.Value = obj.CalculateValue(a,b);
...
end
7-17
% obj is the object being constructed function obj = myClass(arg) obj.propert1 = arg*10; obj.method1; ... end
end end
See Basic Structure of Constructor Methods on page 7-22 for ways to handle superclass constructors.
7-18
Constructing Subclasses
Subclass constructor functions must explicitly call superclass constructors if the superclass constructors require input arguments. The subclass constructor must specify these arguments in the call to the superclass constructor using the constructor output argument and the returned object must be assigned to the constructor output argument. Here is the syntax:
classdef MyClass < SuperClass function obj = MyClass(arg) obj = obj@SuperClass(ArgumentList); ... end end
The class constructor must make all calls to superclass constructors before any other references to the object, such as assigning property values or calling ordinary class methods. Also, a subclass constructor can call a superclass constructor only once.
MATLAB calls any uncalled constructors in the left-to-right order in which they are specified in the classdef line. MATLAB passes no arguments these functions.
7-19
For example, in the following example the superclass shape constructor is called using some default values when the cube constructor has been called with no arguments:
classdef cube < shape properties SideLength = 0; Color = [0 0 0]; end methods function cube_obj = cube(length,color,upvector,viewangle) if nargin == 0 % Provide default values if called with no arguments super_args{1} = [0 0 1]; super_args{2} = 10; else super_args{1} = upvector; super_args{2} = viewangle; end cube_obj = cube_obj@shape(super_args{:}); if nargin > 0 % Use value if provided cube_obj.SideLength = length; cube_obj.Color = color; end ... end ... end
7-20
subclass constructors. Here is how you can implement this behavior in the cube constructor:
function obj = cube(length,color,upvector,viewangle) if nargin == 0 % Create empty cell array if no input argsuments super_args = {}; else % Use specified argsuments super_args{1} = upvector; super_args{2} = viewangle; end % Call the superclass constructor with the % empty cell array (no arguments) if nargin == 0 % otherwise cell array is not empty cube_obj = cube_obj@shape(super_args{:}); if nargin > 0 cube_obj.SideLength = length; cube_obj.Color = color; end ... end
More on Subclasses
See Creating Subclasses Syntax and Techniques on page 10-7 for information on creating subclasses.
7-21
7-22
obj = obj@baseClass1(args{:}); %%% Post Initialization %%% % Any code, including access to object obj.classMethod(...); obj.ComputedValue = compvalue; ... end ... end ... end
See Creating Object Arrays on page 8-3 for information on creating object arrays in the constructor.
7-23
Static Methods
In this section... Why Define Static Methods on page 7-24 Calling Static Methods on page 7-25
7-24
Static Methods
Example Using Events to Update Graphs on page 9-30 provides an example that uses a static method to create a set of objects representing graphs.
Calling the pi method of MyClass in the previous section would require this statement:
value = MyClass.pi(.001);
You can also invoke static methods using an instance of the class, like any method:
obj = MyClass; value = obj.pi(.001);
7-25
7-26
Overloading MATLAB Functions for the DocPolynom Class on page 16-16 provides examples. Methods That Modify Default Behavior on page 15-2 provides a discussion of methods that you might typically implement for MATLAB classes.
Implementing Operators for Your Class on page 15-35 provides information on methods to overload. Defining Arithmetic Operators for DocPolynom on page 16-14 provides examples.
7-27
Within a class, all names exist in the same name space and must be unique. A class cannot define two methods with the same name and a class cannot define a subfunction with the same name as a method. The name of a static method is considered without its class prefix. Thus, a static method name without its class prefix cannot match the name of any other method.
7-28
Ordinarily, objects have equal precedence and the method associated with the left-most object is called. However, there are two exceptions: User-defined classes have precedence over MATLAB built-in classes. User-defined classes can specify their relative precedence with respect to other user-defined classes using the InferiorClasses attribute. In Example A Polynomial Class on page 16-2, the polynom class defines a plus method that enables the addition of DocPolynom objects. Given the object p:
p = DocPolynom([1 0 -2 -5]) p = x^3-2*x-5
the expression:
1 + p ans = x^3-2*x-4
calls the DocPolynom plus method (which converts the double, 1, to a DocPolynom object and then implements the addition of two polynomials). The user-defined DocPolynom class has precedence over the builtin double class.
7-29
places a class below other classes in the precedence hierarchy. Define the InferiorClasses property in the classdef statement:
classdef (InferiorClasses = {?class1,?class2}) myClass
This attribute establishes a relative priority of the class being defined with the order of the classes listed.
calls @classA/plus.m. Conversely, if objectB is above objectA in the precedence hierarchy, then the MATLAB runtime calls @classB/plus.m. See Rules for Naming to Avoid Conflicts on page 7-27 for related information.
7-30
Callback Arguments
You can use class methods as callbacks for Handle Graphics objects by specifying the callback as an anonymous function. Anonymous functions enable you to pass the arguments required by methods (i.e., the first argument is a class object) and graphics object callbacks (i.e., the event source and the event data), as well as any other arguments you want to pass to the function. The following links provide general information on graphics object callbacks and anonymous functions.
Background Information
Function Handle Callbacks Information on graphics object callbacks Anonymous Functions Information about using anonymous functions
You must define the callback method with the following signature:
method_name(object,src,event)
7-31
This class assigns the Callback property in a separate set statement so that the value objects (seal) Slider property has been defined when you create the function handle. Otherwise, Handle Graphics freezes seal before the uicontrols handle is assigned to the Slider property.
7-32
Class Properties
The class defines properties to store graphics object handles and the calculated color limits:
classdef SeaLevelAdjuster < handle properties Figure = []; Axes = []; Image = []; CLimit = []; Slider = []; end end
7-33
Class Constructor
The class constructor creates the graphics objects and assigns the slider callback (last line in code snippet):
methods function seal = SeaLevelAdjuster(x,map) seal.Figure = figure('Colormap',map,... 'Resize','off',... 'Position',[100 100 560 580]); seal.Axes = axes('DataAspectRatio',[1 1 1],... 'XLimMode','manual',... 'YLimMode','manual',... 'DrawMode','fast',... 'Parent',seal.Figure); seal.Image = image(x,'CDataMapping','scaled','Parent',seal.Axes); seal.CLimit = get(seal.Axes,'CLim'); seal.Slider = uicontrol('Style','slider',... 'Parent',seal.Figure,... 'Max',seal.CLimit(2),... 'Min',seal.CLimit(1)-1,... 'Value',seal.CLimit(1),... 'Units','normalized',... 'Position',[.9286 .1724 .0357 .6897],... 'SliderStep',[.005 .002],... 'Callback',@(src,event)slider_cb(seal)); end % SeaLevelAdjuster end % methods
The callback function for the slider is defined to accept the three required arguments a class instance, the handle of the event source, and the event data:
methods function slider_cb(seal) min_val = get(seal.Slider,'Value'); max_val = max(max(get(seal.Image,'CData'))); set(seal.Axes,'CLim',[min_val max_val]) drawnow end % slider_cb end % methods
7-34
After loading the data, create a SeaLevelAdjuster object for the image:
seal = SeaLevelAdjuster(X,map)
Move the slider to change the apparent sea level and visualize what would happen to Cape Cod if the sea level were to rise.
7-35
50
100
150
200
250
300
7-36
8
Object Arrays
Information About Arrays on page 8-2 Creating Object Arrays on page 8-3 Concatenating Objects of Different Classes on page 8-13
Object Arrays
8-2
8-3
Object Arrays
Now suppose you execute the following statement (which is valid MATLAB code):
a(1,7) = SimpleClass(7) ??? Input argument "v" is undefined. Error in ==> SimpleClass>SimpleClass.SimpleClass at 7 obj.Value = v;
This error occurs because MATLAB is attempting to call the constructor with no arguments to initialize elements in the array a(1,1:6). Therefore, you must ensure the constructor function supports the no input argument syntax. The simplest solution is to test nargin and let the case when nargin == 0 execute no code, but not error:
classdef SimpleClass properties Value end methods function obj = SimpleClass(v) if nargin > 0 obj.Value = v;
8-4
You can provide a default for the property in the properties definition block or assign a value to the input argument in the constructor, when calling the SimpleClass constructor with no arguments.. Using the revised class definition, the previous array assignment statement executes without error:
a(1,7) = SimpleClass(7) a = 1x7 SimpleClass Properties: Value
The object assigned to element a(1,7) used the input argument when MATLAB created it:
a(1,7) ans = SimpleClass Properties: Value: 7
However, MATLAB created the objects contained in elements a(1,1:6) with no input argument and initialized the value of the Value property to empty []. For example:
a(1,1) ans = SimpleClass Properties: Value: []
MATLAB calls the SimpleClass constructor once and copies the value to the Value properties of each object.
8-5
Object Arrays
creates a 5by0 empty array of class SimpleClass. Calling empty with no arguments returns a 0by0 empty array.
8-6
If you make an assignment to a property value, MATLAB calls the SimpleClass constructor to grow the array to the require size:
>> ary(5).Value = 7; >> ary(5).Value ans = 7 >> ary(1).Value ans = []
In this case, MATLAB populates array elements one through five with SimpleClass objects created by calling the class constructor with no arguments. Then MATLAB assigns the property value 7 to the object at ary(5).
8-7
Object Arrays
The property RandNumb contains a random number that is assigned from the InitArray class constructor. The next section uses the InitArray class to show when MATLAB calls the class constructor when expanding an array.
As expected, the element in the index location 4,5 is an instance of the InitArray class. Element 1,1 is also an instance of the InitArray class and its RandNumb property is set to the random number 91, in this case. MATLAB called the class constructor to create an object for the remaining array elements:
A(1,1).RandNumb ans = 91
However, MATLAB copies this second instance to create all remaining array elements:
A(2,2).RandNumb
8-8
When initializing an object array, MATLAB assigns a copy of a single default object to the empty elements in the array. MATLAB gives each object a unique handle so that later you can assign different property values to each object. This means that
A(1,1) == A(2,2) ans = 0
results in two calls to the class constructor. The first creates the object for array element A(4,5). The second creates a default object (no arguments passed to the constructor) that MATLAB copies to all remaining empty array elements. See Indexing Multidimensional Arrays and Reshaping Multidimensional Arrays for information on array manipulation. See Initializing Properties to Unique Values on page 3-10 for information on assigning values to properties. See Indexed Reference and Assignment on page 15-13 for information on implementing subsasgn methods for your class.
8-9
Object Arrays
Create an array of ObjArray objects and assign all values of the RegProp property to the propvalues cell array:
for k = 1:5 a(k) = ObjArray; end propvalues = {a.RegProp} propvalues = [96] [49] [81] [15] [43]
8-10
classdef ObjArray < dynamicprops properties RegProp end methods function obj = ObjArray % Assign property a random integer obj.RegProp = randi(100); end end end
Create an object array and add dynamic properties to each member of the array:
% Define elements 1 and 2 as ObjArray objects a(1) = ObjArray; a(2) = ObjArray; % Add dynamic properties to each object and assign a value a(1).addprop('DynoProp'); a(1).DynoProp = 1; a(2).addprop('DynoProp'); a(2).DynoProp = 2;
You can get the values of the ordinary properties, as with any array:
a.RegProp ans = 4 ans = 85
MATLAB returns an error if you try to access the dynamic properties of all array elements using this syntax.
a.DynoProp
8-11
Object Arrays
You must refer to each object individually to access dynamic property values:
a(1).DynoProp ans = 1 a(2).DynoProp ans = 2
8-12
Basic Knowledge
The material presented in this section builds on an understanding of the information presented in the following sections. Specifying Class Precedence on page 4-17, Class Attributes on page 4-5, Creating Object Arrays on page 8-3.
Concatenating Objects
Concatenation combines objects into arrays:
ary = [obj1,obj2,obj3,...,objn]; % size of ary is 1-by-n
8-13
Object Arrays
The class of the resulting array, ary, is the same as the class of the objects being concatenated. Concatenating unlike objects is possible if MATLAB can convert objects to the dominant class. MATLAB attempts to convert unlike objects by: Calling the inferior objects converter method, if one exists (see Implementing Converter Methods on page 8-17 for an example). Passing an inferior object to the dominant class constructor to create an object of the dominant class. If conversion of the inferior objects is successful, MATLAB returns an array that is of the dominant class. If conversion is not possible, MATLAB returns an error.
8-14
stored in a property. If this is not a desired result, then ensure that class constructors include adequate error checking. For example, consider the class ColorClass and two subclasses, RGBColor and HSVColor:
classdef ColorClass properties Color end end
The class RGBColor inherits the Color property from ColorClass. RGBColor stores a color value defined as a three-element vector of red, green, and blue (RGB) values. The constructor does not restrict the value of the input argument. It assigns this value directly to the Color property.
classdef RGBColor < ColorClass % Class to contain RGB color specification methods function obj = RGBColor(rgb) if nargin > 0 obj.Color = rgb; end end end end
The class HSVColor also inherits the Color property from ColorClass. HSVColor stores a color value defined as a three-element vector of hue, saturation, value (HSV) values.
classdef HSVColor < ColorClass % Class to contain HSV color specification methods function obj = HSVColor(hsv) if nargin > 0 obj.Color = hsv; end end end
8-15
Object Arrays
end
Create an instance of each class and concatenate them into an array. The RGBColor object is dominant because it is the left most object and neither class defines a dominance relationship:
crgb = RGBColor([1 0 0]); chsv = HSVColor([0 1 1]); ary = [crgb,chsv]; class(ary) ans = RGBColor
MATLAB can combine these different objects into an array because it can pass the inferior object of class HSVColor to the constructor of the dominant class. However, notice that the Color property of the second RGBColor object in the array actually contains an HSVColor object, not an RGB color specification:
ary(2).Color ans = HSVColor Properties: Color: [0 1 1]
Avoid this undesirable behavior by: Implementing converter methods Performing argument checking in class constructors before assigning values to properties The next section shows updates to these classes.
8-16
Create an array of RGBColor and HSVColor objects with the revised superclass:
crgb = RGBColor([1 0 0]); chsv = HSVColor([0 1 1]); ary = [crgb,chsv]; class(ary) ans = RGBColor
MATLAB calls the converter method for the HSVColor object, which it inherits from the superclass. The second array element is now an RGBColor object with an RGB color specification assigned to the Color property:
ary(2)
8-17
Object Arrays
If the left-most object is of class HSVColor, the array ary is also of class HSVColor, and MATLAB converts the Color property data to HSV color specification.
ary = [chsv crgb] ary = 1x2 HSVColor Properties: Color ary(2).Color ans = 0 1 1
Defining a converter method in the superclass and adding better argument checking in the subclass constructors produces more predicable results. Here is the RGBColor class constructor with argument checking:
classdef RGBColor < ColorClass2 methods function obj = RGBColor(rgb) if nargin == 0 rgb = [0 0 0]; else if ~(strcmp(class(rgb),'double')...
8-18
&& size(rgb,2) == 3 && max(rgb) <= 1 && min(rgb) >= 0) error('Specify color as RGB values') end end obj.Color = rgb; end end end
Your applications might require additional error checking and other coding techniques. The classes in these examples are designed only to demonstrate concepts. See Class Constructor Methods on page 7-15 for more information on writing class constructors. See Chapter 10, Building on Other Classes for more information on inheritance.
8-19
Object Arrays
8-20
9
Events Sending and Responding to Messages
Learning to Use Events and Listeners on page 9-2 Events and Listeners Concepts on page 9-9 Event Attributes on page 9-14 Defining Events and Listeners Syntax and Techniques on page 9-15 Listening for Changes to Property Values on page 9-23 Example Using Events to Update Graphs on page 9-30
Quick Overview
When using events and listeners: Only handle classes can define events and listeners (See Naming Events on page 9-15 for syntax). Call the handle notify method to trigger the event (See Triggering Events on page 9-15, and Defining and Triggering an Event on page 9-4, for examples). The event notification broadcasts the named event to all listeners registered for this event.
9-2
Use the handle addlistener method to associate a listener with an object that will be the source of the event (Listening to Events on page 9-16, Creating a Listener for the Overflow Event on page 9-5, and Creating a Listener for the Property Event on page 9-8). When adding a listener, pass a function handle for the listener callback function using a syntax such as the following:
addlistener(eventObject,'EventName',@functionName) for an
ordinary function.
addlistener(eventObject,'EventName',@Obj.methodName) for a
method of Obj.
addlistener(eventObject,'EventName',@ClassName.methodName)
Listener callback functions must define at least two input arguments the event source object handle and the event data (See Defining Listener Callback Functions on page 9-21 for more information). You can modify the data passed to each listener callback by subclassing the event.EventData class (See Defining Event-Specific Data on page 9-18) and Defining the Event Data on page 9-5 for more information).
9-3
as an argument to the notify method, which is the method that you use to trigger the event. See Defining Event-Specific Data on page 9-18 for another example of subclassing event.EventData.
9-4
end
9-5
end
9-6
properties (SetObservable) % Enable property events with SetObservable attribute State = false; end methods function buttonObj = PushButton uicontrol('Style','pushbutton',... 'String','R/B',... 'Callback',@buttonObj.pressed); end end methods (Access = private) % Make push button callback private function pressed(buttonObj,src,event) % #ok<INUSD> % Setting value of State property triggers property set events buttonObj.State = ~buttonObj.State; end end end
9-7
methods function set.Grid(axObj,newGrid) % Set method for Grid property % As push button State changes, % listener sets AxesObj Grid property axObj.PrivGrid = newGrid; if axObj.Grid grid(axObj.MyAxes,'on'); else grid(axObj.MyAxes,'off'); end end function g = get.Grid(axObj) g = axObj.PrivGrid; end end end
9-8
9-9
Listeners execute a callback function when notified that the event has occurred. Defining Listener Callback Functions on page 9-21 You can bind listeners to the lifecycle of the object that defines the event, or limit listeners to the existence and scope of the listener object. Ways to Create Listeners on page 9-19 The following diagram illustrates the event model.
InsufcientFunds 3. Listeners awaiting message execute their callbacks. (The broadcasting object does not necessarily know who is listening.) Listener1 Properties EventName = InsufcientFunds FunctionHandle = @Callback1
InsufcientFunds
9-10
9-11
9-12
Listeners
Listeners encapsulate the response to an event. Listener objects belong to the event.listener class, which is a handle class that defines the following properties: Source Handle or array of handles of the object that generated the event EventName Name of the event Callback Function to execute with an enabled listener receives event notification Enabled Callback function executes only when Enabled is true. See Enabling and Disabling the Listeners on page 9-46 for an example. Recursive Allow listener to cause the same event that triggered the execution of the callback
Recursive is true by default. It is possible to create a situation where infinite recursion reaches the recursion limit and eventually triggers an error. If you set Recursive to false, the listener cannot execute recursively if the callback triggers its own event.
9-13
Event Attributes
Table of Event Attributes
The following table lists the attributes you can set for events. To specify a value for an attribute, assign the attribute value on the same line as the event key word. For example, all the events defined in the following events block have private ListenAccess and NotifyAccess attributes.
events (ListenAccess = 'private', NotifyAccess = 'private') anEvent anotherEvent end
To define other events in the same class definition that have different attribute settings, create another events block. Attribute Name
Hidden
Class
logical Default = false
Description If true, event does not appear in list of events returned by events function (or other event listing functions or viewers). Determines where you can create listeners for the event. public Unrestricted access protected Access from methods in class or derived classes private Access by class methods only (not from derived classes)
ListenAccess enumeration
Default = public
NotifyAccess enumeration
Determines where code can trigger the event public Any code can trigger event protected Can trigger event from methods in class or derived classes private Can trigger event by class methods only (not from derived classes)
Default = public
9-14
Naming Events
Define an event by declaring an event name inside an events block, typically in the class that generates the event. For example, the following class creates an event called ToggledState, which might be triggered whenever a toggle buttons state changes.
classdef ToggleButton < handle properties State = false end events ToggledState end end
Triggering Events
At this point, the ToggleButton class has defined a name that it will associate with the toggle button state changestoggling on and toggling off. However, a class method controls the actual firing of the events. To accomplish this, the ToggleButton class adds a method to trigger the event:
classdef ToggleButton < handle properties State = false end
9-15
events ToggledState end methods ... function OnStateChange(obj,newState) % Call this method to check for state change if newState ~= obj.State obj.State = newState; notify(obj,'ToggledState'); % Broadcast notice of event end end end end
The OnStateChange method calls notify to trigger the event, using the handle of the ToggleButton object that owns the event and the string name of the event.
Listening to Events
Once the call to notify triggers an event, MATLAB broadcasts a message to all registered listeners. To register a listener for a specific event, use the addlistener handle class method. For example, the following class defines objects that listen for the ToggleState event defined in the class ToggleButton.
classdef RespondToToggle < handle methods function obj = RespondToToggle(toggle_button_obj) addlistener(toggle_button_obj,'ToggledState',@RespondToToggle.handleEvnt); end end methods (Static) function handleEvnt(src,evtdata) if src.State disp('ToggledState is true') else disp('ToggledState is false') end % Respond to false ToggleState here % Respond to true ToggleState here
9-16
The class RespondToToggle adds the listener from within its constructor. The class defines the callback (handleEvnt) as a static method that accepts the two standard arguments: src the handle of the object triggering the event (i.e., a ToggleButton object) evtdata an event.EventData object The listener executes the callback when the specific ToggleButton object executes the notify method, which it inherits from the handle class. For example, create instances of both classes:
tb = ToggleButton; rtt = RespondToToggle(tb);
Whenever you call the ToggleButton objects OnStateChange method, notify triggers the event:
tb.OnStateChange(true) ToggledState is true tb.OnStateChange(false) ToggledState is false
Removing Listeners
You can remove a listener object by calling delete on its handle. For example, if the class RespondToToggle above saved the listener handle as a property, you could delete the listener:
classdef RespondToToggle < handle properties ListenerHandle end methods
9-17
function obj = RespondToToggle(toggle_button_obj) hl = addlistener(toggle_button_obj,'ToggledState',@RespondToToggle.handleEvnt); obj.ListenerHandle = hl; end end ... end
With this code change, you can remove the listener from an instance of the RespondToToggle class. For example:
tb = ToggleButton; rtt = RespondToToggle(tb);
At this point, the object rtt is listening for the ToggleState event triggered by object tb. To remove the listener, call delete on the property containing the listener handle:
delete(rtt.ListenerHandle)
You do not need to explicitly delete a listener. MATLAB automatically deletes the listener when the objects lifecycle ends (e.g., when the rtt object is deleted). See Limiting Listener Scope Constructing event.listener Objects Directly on page 9-20 for related information.
9-18
The call to notify uses the ToggleEventData constructor to create the necessary argument.
notify(obj,'ToggledState',ToggleEventData(newState));
The arguments are: obj The object that is the source of the event ToggleState The event name passed as a string @CallbackFunction A function handle to the callback function The listener callback function must accept at least two arguments, which are automatically passed by the MATLAB runtime to the callback. The arguments are: The source of the event (that is, obj in the call to addlistener)
9-19
An event.EventData object, or a subclass of event.EventData , such as the ToggleEventData object described earlier Defining Event-Specific Data on page 9-18. The callback function must be defined to accept these two arguments:
function CallbackFunction(src,evnt) ... end
In cases where the event data (evnt) object is user defined, it must be constructed and passed as an argument to the notify method. For example, the following statement constructs a ToggleEventData object and passes it to notify as the third argument:
notify(obj,'ToggledState',ToggleEventData(newState));
Defining Listener Callback Functions on page 9-21 provides more information on callback syntax.
If you want the listener to persist beyond the normal variable scope, you should use addlistener to create it.
9-20
To re-enable the listener, set Enabled to true. Enabling and Disabling the Listeners on page 9-46 provides an example.
All callback functions must accept at least two arguments: The handle of the object that is the source of the event An event.EventData object or an object that is derived from the event.EventData class (see Defining Event-Specific Data on page 9-18 for an example that extends this class).
9-21
hlistener = addlistener(eventSourceObj,'MyEvent',@obj.listenMyEvent)
Another syntax uses an anonymous function. See the Anonymous Functions section for general information on anonymous functions For example, create a method to use as your callback function and reference this method as a function handle in a call to addlistener or the event.listener constructor:
hlistener = addlistener(eventSourceObj,'MyEvent',@(src,evnt)listenMyEvent(obj,src,evnt))
Variables Used in the Expression provides information on variables used in anonymous functions.
9-22
9-23
arguments, which are passed to the function automatically when called by the listener: Event source a meta.property object describing the object that is the source of the property event Event data a event.PropertyEvent object containing information about the event You can pass additional arguments if necessary. It is often simple to define this method as Static because these two arguments contain most necessary information in their properties. For example, suppose the handlePropEvents function is a static method of the class creating listeners for two properties of an object of another class:
methods (Static) function handlePropEvents(src,evnt) switch src.Name % switch on the property name case 'PropOne' % PropOne has triggered an event ... case 'PropTwo' % PropTwo has triggered an event ... end end end
Another possibility is to use the event.PropertyEvent objects EventName property in the switch statement to key off the event name (PreSet or PostSet in this case). Working with Meta-Classes on page 14-2 provides more information about the meta.property class.
9-24
If the call
addlistener(EventObject,'PropOne','PostSet',@ClassName.handlePropertyEvents);
The arguments are: EventObject handle of the object generating the event PropOne name of the property to which you want to listen PostSet name of the event for which you want to listen @ClassName.handlePropertyEvents function handle referencing a static method, which requires the use of the class name If your listener callback is an ordinary method and not a static method, the syntax is:
addlistener(EventObject,'PropOne','PostSet',@obj.handlePropertyEvents);
where obj is the handle of the object defining the callback method. If the listener callback is a function that is not a class method, you pass a function handle to that function. Suppose the callback function is a package function:
addlistener(EventObject,'PropOne','PostSet',@package.handlePropertyEvents);
9-25
classdef PropEvent < handle % enable property events with the SetObservable attribute properties (SetObservable, AbortSet) PropOne PropTwo end methods function obj = PropEvent(p1,p2) if nargin > 0 obj.PropOne = p1; obj.PropTwo = p2; end end end end
9-26
methods (Static) function handlePropEvents(src,evnt) switch src.Name case 'PropOne' fprintf(1,'PropOne is %s\n',num2str(evnt.AffectedObject.PropOne)) case 'PropTwo' fprintf(1,'PropTwo is %s\n',num2str(evnt.AffectedObject.PropTwo)) end end end end
9-27
classdef AbortTheSet < handle properties (SetObservable, GetObservable, AbortSet) PropOne = 7 end methods function obj = AbortTheSet(val) obj.PropOne = val; addlistener(obj,'PropOne','PreGet',@obj.getPropEvt); addlistener(obj,'PropOne','PreSet',@obj.setPropEvt); end function propval = get.PropOne(obj) disp('get.PropOne called') propval = obj.PropOne; end function set.PropOne(obj,val) disp('set.PropOne called') obj.PropOne = val; end function getPropEvt(obj,src,evnt) disp ('Pre-get event triggered') end function setPropEvt(obj,src,evnt) disp ('Pre-set event triggered') end function disp(obj) % Override disp to avoid accessing property disp (class(obj)) end end end
The class specifies an initial value of 7 for the PropOne property. Therefore, if you create an object with the property value of 7, there is not need to trigger the PreSet event:
>> ats = AbortTheSet(7); get.PropOne called
If you specify a value other than 7, then MATLAB triggers the PreSet event:
9-28
Similarly, if you set the PropOne property to the value 9, the AbortSet attribute prevents the property assignment and the triggering of the PreSet event. Notice also, that there is not PreGet event generated. Only the property get method is called:
>> ats.PropOne = 9; get.PropOne called
If you set the PropOne property to a different value, MATLAB: Calls the property get method to determine if the value is changing Triggers the PreSet event Calls the property set method to set the new value
>> ats.PropOne = 11; get.PropOne called Pre-set event triggered set.PropOne called
9-29
Example Overview
This example defines two classes: fcneval The function evaluator class contains a MATLAB expression and evaluates this expression over a specified range fcnview The function viewer class contains a fcneval object and displays surface graphs of the evaluated expression using the data contained in fcneval. This class defines two events: A class-defined event that occurs when a new value is specified for the MATLAB function A property event that occurs when the property containing the limits is changed The following diagram shows the relationship between the two objects. The
fcnview object contains a fcneval object and creates graphs from the data it
9-30
contains. fcnview creates listeners to change the graphs if any of the data in the fcneval object change.
fcnview Properties fcneval object graph fcneval Properties FofXY Lm observable Data Events UpdateGraph
You can open all files in your editor by clicking this link: Open in editor To use the classes, save the files in folders with the following names:
9-31
@fcneval/fcneval.m @fcnview/fcnview.m @fcnview/createViews.m The @-folders parent folder must be on the MATLAB path.
two-element Limits over which function is evaluated in vector both variables. SetObservable attribute set to true to enable property event listeners. structure with x, y, and z matrices Data resulting from evaluating the function. Used for surface graph. Dependent attribute set to true, which means the get.Data method is called to determine property value when queried and no data is stored.
Data
9-32
Event
UpdateGraph
When Triggered
FofXY property set function (set.FofXY) calls the notify method when a new value is specified for the MATLAB expression on an object of this class.
Method
fcneval
Purpose Class constructor. Inputs are function handle and two-element vector specifying the limits over which to evaluate the function.
FofXY property set function. Called whenever property
grid
A static method (Static attribute set to true) used in the calculation of the data.
Value
fcneval object
Purpose This object contains the data that is used to create the function graphs. Each instance of a fcnview object stores the handle of the axes containing its subplot.
axes handle
9-33
Property
Purpose Setting the event.listener objects Enabled property to true enables the listener; false disables listener. Setting the event.listener objects Enabled property to true enables the listener, false disables listener. Item on context menu used to enable listeners (used to handle checked behavior) Item on context menu used to disable listeners (used to manage checked behavior) Used by event callbacks to update surface data.
HLUpdateGraph event.listener
event
HLLm event.listener
uimenu handle
HDisableCm
uimenu handle
HSurface
surface handle
Method
fcnview createLisn lims updateSurfaceData listenUpdateGraph listenLm delete createViews
Purpose Class constructor. Input is fcneval object. Calls addlistener to create listeners for UpdateGraph and Lm property PostSet listeners. Sets axes limits to current value of fcneval objects Lm property. Used by event handlers. Updates the surface data without creating a new object. Used by event handlers. Callback for UpdateGraph event. Callback for Lm property PostSet event Delete method for fcnview class. Static method that creates an instance of the fcnview class for each subplot, defines the context menus that enable/disable listeners, and creates the subplots
9-34
Purpose
Register a listener for a specific event and attach listener to event-defining object. Trigger an event and notify all registered listeners.
Use the createViews static method to create the graphs of the function. Note that you must use the class name to call a static function:
fcnview.createViews(feobject);
9-35
The createView method generates four views of the function contained in the fcneval object.
Each subplot defines a context menu that can enable and disable the listeners associated with that graph. For example, if you disable the listeners on subplot 221 (upper left) and change the MATLAB expression contained by the fcneval object, only the remaining three subplots update when the UpdateGraph event is triggered:
feobject.FofXY = @(x,y) x.*exp(-x.^.5-y.^.5);
9-36
Similarly, if you change the limits by assigning a value to the feobject.Lm property, the feobject triggers a PostSet property event and the listener callbacks update the graph.
feobject.Lm = [-8 3];
In this figure the listeners are re-enabled via the context menu for subplot 221. Because the listener callback for the property PostSet event also updates the surface data, all views are now synchronized
9-37
9-38
1. A property is assigned a new value. obj.FofXY = @(x,y)x^2+y^2 2. Setting the property runs a set access method, which, in turn, executes notify.
3. The notify method triggers an event, and a message is broadcast. 4. A listener awaiting the message executes its callback. UpdateGraph Listener Properties EventName = UpdateGraph FunctionHandle = @listenUpdateGraph
The fcnview class defines a listener for this event. When fcneval triggers the event, the fcnview listener executes a callback function that performs the follow actions: Determines if the handle of the surface object stored by the fcnview object is still valid (that is, does the object still exist) Updates the surface XData, YData, and ZData by querying the fcneval objects Data property.
9-39
Assigns the expression to the FofXY property Triggers the UpdateGraph event
If fcneval.isSuitable does not return an MException object, the set.FofXY method assigns the value to the property and triggers the UpdateGraph event.
function set.FofXY(obj,func) % Determine if function is suitable to create a surface me = fcneval.isSuitable(func); if ~isempty(me) throw(me) end % Assign property value obj.FofXY = func; % Trigger UpdateGraph event notify(obj,'UpdateGraph'); end
9-40
returns an MException object if it determines that the expression is unsuitable. fcneval.isSuitable calls the MException constructor directly to create more useful error messages for the user.
set.FofXY issues the exception using the MException throw method. Issuing the exception terminates execution of set.FofXY and prevents the method from making an assignment to the property or triggering the UpdateGraph event.
The fcneval.isSuitable method could provide additional test to ensure that the expression assigned to the FofXY property meets the criteria required by the class design.
Other Approaches
The class could have implemented a property set event for the FofXY property and would, therefore, not need to call notify (see Listening for Changes
9-41
to Property Values on page 9-23). Defining a class event provides more flexibility in this case because you can better control event triggering. For example, suppose you wanted to update the graph only if the new data is significantly different. If the new expression produced the same data within some tolerance, the set.FofXY method could not trigger the event and avoid updating the graph. However, the method could still set the property to the new value.
The fcnview object stores a handle to the event.listener object in its HLUpdateGraph property, which is used to enable/disable the listener by a context menu (see Enabling and Disabling the Listeners on page 9-46). The fcnview object (obj) is added to the two default arguments (src, evnt) passed to the listener callback. Keep in mind, the source of the event (src) is the fcneval object, but the fcnview object contains the handle of the surface object that is updated by the callback. The listenUpdateGraph function is defined as follows:
function listenUpdateGraph(obj,src,evnt) if ishandle(obj.HSurface) % If surface exists obj.updateSurfaceData % Update surface data end end
The updateSurfaceData function is a class method that updates the surface data when a different mathematical function is assigned to the fcneval object. Updating a graphics object data is generally more efficient than creating a new object using the new data:
9-42
function updateSurfaceData(obj) % Get data from fcneval object and set surface data set(obj.HSurface,... 'XData',obj.FcnObject.Data.X,... 'YData',obj.FcnObject.Data.Y,... 'ZData',obj.FcnObject.Data.Matrix); end
9-43
1. New limits are assigned. obj.Lm = [-3 5]; 2. The SetObservable attribute of Properties is set to True, so setting the property automatically triggers a PostSet event. Note that methods and events did not have to be declared in myfunceval. 3. A message is broadcast. 4. A listener awaiting the message executes its callback. PostSet
PostSet event.
9-44
The PostSet event does not occur until an actual assignment of the property occurs. The property set function provides an opportunity to deal with potential assignment errors before the PostSet event occurs.
The MATLAB runtime automatically triggers the event so it is not necessary to call notify. Specifying Property Attributes on page 6-7 provides a list of all property attributes.
The fcnview object stores a handle to the event.listener object in its HLLm property, which is used to enable/disable the listener by a context menu (see Enabling and Disabling the Listeners on page 9-46). The fcnview object (obj) is added to the two default arguments (src, evnt) passed to the listener callback. Keep in mind, the source of the event (src) is the fcneval object, but the fcnview object contains the handle of the surface object that is updated by the callback.
9-45
The callback sets the axes limits and updates the surface data because changing the limits causes the mathematical function to be evaluated over a different range:
function listenLm(obj,src,evnt) if ishandle(obj.HAxes) % If there is an axes lims(obj); % Update its limits if ishandle(obj.HSurface) % If there is a surface obj.updateSurfaceData % Update its data end end end
9-46
function enableLisn(obj,src,evnt) obj.HLUpdateGraph.Enabled = true; % Enable listener obj.HLLm.Enabled = true; % Enable listener set(obj.HEnableCm,'Checked','on') % Check Listen set(obj.HDisableCm,'Checked','off') % Uncheck Don't Listen end
The disableLisn function is called when the user selects Dont Listen from the context menu.
function disableLisn(obj,src,evnt) obj.HLUpdateGraph.Enabled = false; % Disable listener obj.HLLm.Enabled = false; % Disable listener set(obj.HEnableCm,'Checked','off') % Unheck Listen set(obj.HDisableCm,'Checked','on') % Check Don't Listen end
9-47
9-48
10
Building on Other Classes
Hierarchies of Classes Concepts on page 10-2 Creating Subclasses Syntax and Techniques on page 10-7 Modifying Superclass Methods and Properties on page 10-13 Subclassing Multiple Classes on page 10-17 Subclassing MATLAB Built-In Classes on page 10-19 Abstract Classes and Interfaces on page 10-50
10
Classification
Organizing classes into hierarchies facilitates the reuse of code and the reuse of solutions to design problems that have already been solved. You can think of class hierarchies as sets supersets (referred to as superclasses or base classes), and subsets (referred to as subclasses or derived classes). For example, the following picture shows how you could represent an employee database with classes.
10-2
Employees
Sales People
Engineers Derived classes Test Engineers SalesPerson (is an Employees) Properties Commission Region Engineer (is an Employees) Properties Products Team
10-3
10
for the intended use of the class. Name, address, and department can be what all employees have in common. When designing classes, your abstraction must contain only those elements that are necessary. For example, the employee hair color and shoe size certainly characterize the employee, but are probably not relevant to the design of this employee class. Their sales region is relevant only to some employee so this characteristic belongs in a subclass.
10-4
10-5
10
subclasses can use. Subclasses can extend an inherited method to provide specialized functionality, while reusing the common aspects. See Modifying Superclass Methods and Properties on page 10-13 for more information on this process. Interface inheritance is useful in cases where you want a group of classes to provide a common interface, but these classes create specialized implementations of methods and properties that define the interface. You create an interface using an abstract class as the superclass. This class defines the methods and properties that you must implement in the subclasses, but does not provide an implementation, in contrast to implementation inheritance. The subclasses must provide their own implementation of the abstract members of the superclass. To create an interface, define methods and properties as abstract using their Abstract attribute. See Abstract Classes and Interfaces on page 10-50 for more information and an example.
10-6
Defining a Subclass
To define a class that is a subclass of another class, add the superclass to the classdef line after a < character:
classdef classname < superclassname
When inheriting from multiple classes, use the & character to indicate the combination of the superclasses:
classdef classname < super1 & super2
See Class Member Compatibility on page 10-17 for more information on deriving from multiple superclasses.
Class Attributes
Subclasses do not inherit superclass attributes.
10-7
10
function s = stock(asset_args,...) if nargin == 0 ... end s = s@asset(asset_args); % call asset constructor ... end end end
Constructing Subclasses on page 7-19 provides more information on creating subclass constructor methods.
10-8
... end s = [email protected](asset_args) % call asset constructor s = [email protected](member_args) % call member constructor ... end end end
Explicitly calling each superclass constructor enables you to: Pass arguments to superclass constructors Control the order in which MATLAB calls the superclass constructors If you do not explicitly call the superclass constructors from the subclass constructor, MATLAB implicitly calls these constructors with no arguments. Therefore, the superclass constructors must support no argument syntax. See Supporting the No Input Argument Case on page 7-18 for more information. In the case of multiple superclasses, MATLAB does not guarantee any specific calling sequence. If the order in which MATLAB calls the superclass constructors is important, you must explicitly call the superclass constructors from the subclass constructor.
10-9
10
name = ''; pps = 0; end s = [email protected](name) % call superclass constructor s.SharePrice = pps; % assign a property value end end end
Class B inherits properties x and y from class A. The class B constructor calls the class A constructor to initialize x and then assigns a value to y.
classdef B < A methods
10-10
Class C accepts values for the properties x and y and passes these values to the class B constructor, which in turn calls the class A constructor:
classdef C < B methods function obj = C(x,y) obj = obj@B(x,y); end end end
ClassA
ClassB
ClassC
MATLAB always calls the most specific class constructor (ClassC in this case) first. This approach enables you to process input arguments and perform any necessary setup before calling the superclass constructors.
10-11
10
If you do not make an explicit call to a superclass constructor from the subclass constructor, MATLAB makes the implicit call before accessing the object. The order is always from most specific to least specific and all the superclass constructors must finish executing before the subclass can access the object. You can change the order in which class constructors are called by calling superclass constructors explicitly from the subclass constructor.
The old class constructor must be callable with zero input arguments. If not, see Old Class Constructor Requires Arguments on page 10-12. This technique is useful when reloading objects that you saved using the old class name. However, the class of the object reflects the new name. For example,
class(obj)
10-12
10-13
10
function foo(obj)
preprocessing steps
See Invoking Superclass Methods in Subclass Methods on page 7-13 for more on this syntax.
The subclass does not reimplement the foo method, it reimplements only the methods that carry out the series of steps (step1(obj), step2(obj), step3(obj)). That is, the subclass can specialize the actions taken by each step, but does not control the order of the steps in the process. When you pass
10-14
a subclass object to the superclass foo method, MATLAB calls the subclass step methods because of the dispatching rules.
classdef sub < super ... methods (Access = protected) function step1(obj)
subclass version
10-15
10
properties (Access = private) Prop = 2; end methods function p = superMethod(obj) p = obj.Prop; end end end classdef Sub < Super properties Prop = 1; end end
If you create an instance of the subclass and use it to call the superclass method, MATLAB access the private property of the methods class:
>> subObj = Sub subObj = Sub Properties: Prop: 1 Methods, Superclasses >> obj.superMethod ans = 2
10-16
Property Conflicts
If two or more superclasses define a property with the same name, then at least one of the following must be true: All, or all but one of the properties must have their SetAccess and GetAccess attributes set to private The properties have the same definition in all superclasses (for example, when all superclasses inherited the property from a common base class)
Method Conflicts
If two or more superclasses define methods with the same name, then at least one of the following must be true: The methods Access attribute is private so only the defining superclass can access the method. The method has the same definition in all derived classes. This situation can occur when all superclasses inherit the method from a common base class and none of the superclasses override the inherited definition. The subclass redefines the method to disambiguate the multiple definitions across all superclasses. This means that the superclass methods must not have their Sealed attribute set to true.
10-17
10
Only one superclass defines the method as Sealed, in which case, the subclass adopts the sealed method definition. The superclases define the methods as Abstract and rely on the subclass to define the method.
Event Conflicts
If two or more superclasses define events with the same name, then at least one of the following must be true: The events ListenAccess and NotifyAccess attributes must be private. The event has the same definition in all superclasses (for example, when all superclasses inherited the event from a common base class)
10-18
10-19
10
Define unique operations to perform on class data. For example, subclass double and add methods to your subclass that restrict values to prime numbers. Be able to use methods of the built-in class and other built-in functions directly with objects of the subclass. For example, you do not need to reimplement all the mathematical and array manipulation operators if you derived from a class that has these operators already. See Built-In Classes You Cannot Subclass on page 10-20 for a list of which MATLAB built-in classes you can subclass.
Generally, you can use an object of the subclass with any of the inherited methods and any functions coded in MATLAB that normally accept input arguments of the same class as the superclass. See Behavior of Built-In Functions with Subclass Objects on page 10-21 for information on other required methods.
10-20
Behavior Categories
When you call an inherited method on a subclass of a built-in class, the result of that call depends on the nature of the operation performed by the method. The behaviors of these methods fit into several categories. Operations on data values return objects of the superclass. For example, if you subclass double and perform addition on two subclass objects, MATLAB adds the numeric values and returns a value of class double. Operations on the orientation or structure of the data return objects of the subclass. Methods that perform these kinds of operations include, reshape, permute, transpose, and so on. Converting a subclass object to a built-in class returns an object of the specified class. Functions such as uint32, double, char, and so on, work with subclass objects the same as they work with superclass objects. Comparing objects or testing for inclusion in a specific set returns logical or built-in objects, depending on the function. Functions such as isequal, ischar, isobject, and so on. Indexing expressions return objects of the subclass. If the subclass defines properties, then default indexing no longer works and the subclass must define its own indexing methods. See Subclasses That Define Properties on page 10-22 for more information.
10-21
10
Concatenation returns an object of the subclass. If the subclass defines properties, then default concatenation no longer works and the subclass must define its own concatenation methods. See Subclasses That Define Properties on page 10-22 for more information. To list the built-in functions that work with a subclass of a built-in class, use the methods function.
10-22
You can create an instance of the class DocSimpleDouble and call any methods of the double class.
sc = DocSimpleDouble(1:10); sc = DocSimpleDouble double data: 1 2 3 4
10
10-23
10
Methods, Superclasses
Calling a method inherited from class double that operates on the data, like sum, returns a double and, therefore, uses the display method of class double:
sum(sc) ans = 55
You can index sc like an array of doubles. The returned value is the class of the subclass, not double:
a = sc(2:4) a = DocSimpleDouble double data: 2 3 4 Methods, Superclasses
10
Calling a method that modifies the order of the data elements operates on the data, but returns an object of the subclass:
sc = DocSimpleDouble(1:10); sc(1:5) = 5:-1:1; a = sort(sc) a = DocSimpleDouble double data: 1 2 3 4 Methods, Superclasses
10
10-24
Extending the Subclass. You can extend the DocSimpleDouble with specialized methods to provide custom behavior. For example, see Example A Class to Manage uint8 Data on page 10-28.
10-25
10
Indexing Methods
Built-in classes use specially implemented versions of the subsref, subsasgn, and subsindex methods to implement indexing (subscripted reference and assignment). When you index a subclass object, only the built-in data is referenced (not the properties defined by your subclass). For example, indexing element 2 in the DocSimpleDouble subclass object returns the second element in the vector:
sc = DocSimpleDouble(1:10); a = sc(2) a = DocSimpleDouble double data: 2 Methods, Superclasses
The value returned from an indexing operation is an object of the subclass. You cannot make subscripted references if your subclass defines properties unless your subclass overrides the default subsref method. Assigning a new value to the second element in the DocSimpleDouble object operates only on the superclass data:
sc(2) = 12 sc = DocSimpleDouble double data: 1 12 3 4 Methods, Superclasses
10
The subsref method also implements dot notation for methods. See Example Adding Properties to a Built-In Subclass on page 10-35 for an example of a subsref method.
Concatenation Functions
Built-in classes use the functions horzcat, vertcat, and cat to implement concatenation. When you use these functions with subclass objects of the same type, MATLAB concatenates the superclass data to form a new object. For example, you can concatenate objects of the DocSimpleDouble class:
10-26
sc1 = DocSimpleDouble(1:10); sc2 = DocSimpleDouble(11:20); [sc1 sc2] ans = DocSimpleDouble double data: Columns 1 through 13 1 14 [sc1; sc2] ans = DocSimpleDouble double data: 1 11 2 12 3 13 4 14 5 15 6 16 7 17 8 18 9 19 10 20 2 15 3 16 4 17 5 18 6 19 7 20 8 9 10 11 12 13 Columns 14 through 20 Methods, Superclasses
Methods, Superclasses
5 15
6 16
7 17
8 18
9 19
10 20
If the subclass of built-in class defines properties, you cannot concatenate objects of the subclass. Such an operation does not make sense because there is no way to know how to combine properties of different objects. However, your subclass can define custom horzcat and vertcat methods to support concatenation in whatever way makes sense for your subclass. See Concatenating DocExtendDouble Objects on page 10-40 for an example.
10-27
10
10-28
% Get uint8 data and setup call to imagesc function h = showImage(obj) data = uint8(obj); figure; colormap(gray(256)) h = imagesc(data,[0 255]); axis image brighten(.2) end end end
10-29
10
50
100
150
200
250
50
100
150
200
250
Because DocUint8 subclasses uint8, you can use any of its methods. For example,
size(img1) ans = 280 272
Indexing Operations
Inherited methods perform indexing operations, but return objects of the same class as the subclass.
10-30
Therefore, you can index into the image data and call a subclass method:
showImage(img1(100:200,1:160));
Subscripted reference operations (controlled by the inherited subsref method) return a DocUint8 object.
10-31
10
Subscripted assignment operations (controlled by the inherited subsasgn method) return a DocUint8 object.
50
100
150
200
250
50
100
150
200
250
Concatenation Operations
Concatenation operations work on DocUint8 objects because this class inherits the uint8 horzcat and vertcat methods, which return a DocUint8 object:
showImage([img1 img1]);
10-32
50 100 150 200 250 50 100 150 200 250 300 350 400 450 500
Data Operations
Methods that operate on data values, such as arithmetic operators, always return an object of the built-in type (not of the subclass type). For example, multiplying DocUint8 objects returns a uint8 object:
showImage(img1.*.8); ??? Undefined function or method 'showImage' for input arguments of type 'uint8'.
If you must be able to perform operations of this type, implement a subclass method to override the inherited method. The times method implements
10-33
10
array (element-by-element) multiplication. See Implementing Operators for Your Class on page 15-35 for a list of operator method names. For example:
function o = times(obj,val) u8 = uint8(obj).*val; % Call uint8 times method o = DocUint8(u8); end
Keep in mind that when you override a uint8 method, MATLAB calls the subclass method and no longer dispatches to the base class method. Therefore, explicitly call the uint8 times method or an infinite recursion can occur. Make the explicit call in this statement of the DocUint8 times method:
u8 = uint8(obj).*val;
After adding the times method to DocUint8, you can use the showImage method in expressions like:
showImage(img1.*1.8);
10-34
50
100
150
200
250
50
100
150
200
250
Methods Implemented
The following methods modify the behavior of the DocExtendDouble class:
10-35
10
DocExtendDouble The constructor supports a no argument syntax that initializes properties to empty values. subsref Enables subscripted reference to the superclass part (double) of the subclass, dot notation reference to the DataString property, and dot notation reference the built-in data via the string Data (the double data property is hidden). horzcat Defines horizontal concatenation of DocExtendDouble objects as the concatenation of the superclass part using the double class horzcat method and forms a cell array of the string properties. vertcat The vertical concatenation equivalent of hortzcat (both are required). char A DocExtendDouble to char converter used by horzcat and vertcat. disp DocExtendDouble implements a disp method to provide a custom display for the object.
Property Added
The DocExtendDouble class defines the DataString property to contain text that describes the data contained in instances of the DocExtendDouble class. Keep in mind that the superclass part (double) of the class contains the data.
10-36
str = ''; elseif nargin == 1 str = ''; end obj = obj@double(data); obj.DataString = str; end function sref = subsref(obj,s) % Implements dot notation for DataString and Data % as well as indexed reference switch s(1).type case '.' switch s(1).subs case 'DataString' sref = obj.DataString; case 'Data' sref = double(obj); if length(s)>1 && strcmp(s(2).type, '()') sref = subsref(sref,s(2:end)); end end case '()' sf = double(obj); if ~isempty(s(1).subs) sf = subsref(sf,s(1:end)); else error('Not a supported subscripted reference') end sref = DocExtendDouble(sf,obj.DataString); end end function newobj = horzcat(varargin) % Horizontal concatenation - cellfun calls double % on all object to get superclass part. cellfun call local char % to get DataString and the creates new object that combines % doubles in vector and chars in cell array and creates new object d1 = cellfun(@double,varargin,'UniformOutput',false ); data = horzcat(d1{:});
10-37
10
str = horzcat(cellfun(@char,varargin,'UniformOutput',false)); newobj = DocExtendDouble(data,str); end function newobj = vertcat(varargin) % Need both horzcat and vertcat d1 = cellfun(@double,varargin,'UniformOutput',false ); data = vertcat(d1{:}); str = vertcat(cellfun(@char,varargin,'UniformOutput',false)); newobj = DocExtendDouble(data,str); end function str = char(obj) % Used for cat functions to return DataString str = obj.DataString; end function disp(obj) % Change the default display disp(obj.DataString) disp(double(obj)) end end end
Create an instance of DocExtendDouble and notice that the display is different from the default:
ed = DocExtendDouble(1:10,'One to ten') ed = One to ten 1 2 3 4 5 6
10
The sum function continues to operate on the superclass part of the object:
sum(ed) ans = 55
Subscripted assignment works on the superclass part of the object so there is no need to implement a subsasgn method; MATLAB uses the default
10-38
subsasgn. However, the following indexed assignment statement does cause a call to the DocExtendDouble constructor to convert the right-hand side of the assignment to a DocExtendDouble object. The expression 5:-1:1 results in values that are of class double. Therefore, the DocExtendDouble constructor must support a syntax requiring only one argument (there is no str argument). ed(1:5) = 5:-1:1 ed = One to ten 5 4 3
10
10
10-39
10
whos Name c ed
Bytes 20 156
You can access the superclass part of the object using dot notation with the Data property because the DocExtendDouble subsref method provides this capability:
d = ed.Data d = 1 2 3 whos Name Size d 1x10 ed 1x10
5 Bytes 80 156
10
10-40
'Ten to one' 4 5 7 6
6 5
7 4
8 3
9 2
10 1
Both horzcat and vertcat return a new object of the same class as the subclass.
10-41
10
Name dsubref
Size 1x4
Bytes 32
Class double
Attributes
Create an object and assign to the superclass part of the object the values 1:10:
sd = DocSimpleDouble(1:10);
The numel function returns the number of elements in the superclass part:
numel(sd) ans =
10-42
10
numel([sd;sd]) ans = 20
The DocSimpleDouble class inherits the indexing behavior of the double class:
sdsubref = sd(7:end); whos sdsubref Name Size sdsubref 1x4
Bytes 88
Class DocSimpleDouble
Attributes
Create an instance of this class and assign a ten-element vector to the Value property:
vs = VerySimpleClass; vs.Value = 1:10;
10-43
10
numel([vs;vs]) ans = 2 vs is a scalar object, as opposed to an array of VerySimpleClass objects. The Value property is an array of doubles: size(vs.Value) ans = 1 10
Bytes 32
Class double
Attributes
10-44
MATLAB does not apply scalar expansion to object array property value assignment. Use the deal function for this purpose:
[vsArray.Value] = deal(1:10);
Indexing rules for object arrays are equivalent to those of struct arrays:
v1 = vsArray(1).Value; >> whos v1 Name Size v1 1x10
Bytes 80
Class double
Attributes
vsArray(1).Value(6) ans = 6
Overloading size
Subclasses of built-in classes inherit a size method, which operates on the superclass part of the subclass object. If you want size to behave in another way, you can override it by defining your own size method in your subclass. Keep in mind that other MATLAB functions use the values returned by size. If you change the way size behaves, ensure that the values returned make sense for the intended use of your class.
10-45
10
Both subsref and subsasgn use numel: subsref numel computes the number of expected outputs (nargout) returned subsref subsasgn numel computes the number of expected inputs (nargin) to that MATLAB assigns as a result of a call to subsasgn Subclasses of built-in classes always return scalar objects as a result of subscripted reference and always use scalar objects for subscripted assignment. The numel function returns the correct value for these operations and there is, therefore, no reason to overload numel. If you define a class in which nargout for subsref or nargin for subsasgn is different from the value returned by the default numel, then overload numel for that class to ensure that it returns the correct values.
10-46
Class Definition
Here is the definition of the DocMuxCard class. Notice that the input port rates initialize the int32 portion of class.
classdef DocMuxCard < int32 properties InPutNames % cell array of strings OutPutName % a string end properties (Dependent = true) OutPutRate end methods function obj = DocMuxCard(inptnames, inptrates, outpname) obj = obj@int32(inptrates); % initial the int32 class portion obj.InPutNames = inptnames; obj.OutPutName = outpname; end function x = get.OutPutRate(obj) x = sum(obj); % calculate the value of the property end function x = subsref(card, s) if strcmp(s(1).type,'.') base = subsref@int32(card, s(1)); if isscalar(s) x = base; else x = subsref(base, s(2:end)); end else x = subsref(int32(card), s); end end
10-47
10
end end
You can treat an DocMuxCard object like an int32. For example, this statement accesses the int32 data in the object to determine the names of the input ports that have a rate of 12:
>> omx.InPutNames(omx==12) ans = 'inp2' 'inp3'
Indexing the DocMuxCard object accesses the int32 vector of input port rates:
>> omx(1:2) ans = 3 12
The OupPutRate property get access method uses sum to sum the output port rates:
>> omx.OutPutRate
10-48
ans = 75
10-49
10
Abstract Classes
An abstract class serves as a basis (that is, a superclass) for a group of related subclasses. It forms the abstractions that are common to all subclasses by specifying the common properties and methods that all subclasses must implement. However, you cannot instantiate the abstract class. You can only create instances of the subclasses. These subclasses are sometimes referred to as concrete classes. Abstract classes are useful for describing functionality that is common to a group of classes, but requires unique implementations within each class. This approach is often called an interface because the abstract class defines the interface of each subclass without specifying the actual implementation.
10-50
The subclasses must implement methods with the same names. The names and number of arguments can be different. However, the abstract class typically conveys details about the expected implementation via its comments and argument naming.
Abstract Properties
For properties that have Abstract attributes set to true: Concrete subclasses must redefine abstract properties without the Abstract attribute set to true and must use the same values for SetAccess and GetAccess attributes as the base class. Abstract properties cannot define set or get access methods (see Property Set and Get Access Methods on page 6-12) and cannot specify initial values. The subclass must define the property and then can create set or get access methods and specify initial values.
Abstract Methods
For methods that have Abstract attributes set to true: Abstract methods have no implementation in the abstract class. The method has a normal function line (without the function or end key words) that can include input and output argument lists. Subclasses are not required to support the same number of input and output arguments and do not need to use the same argument names. However, subclasses generally use the same signature when implementing their version of the method.
10-51
10
must implement a Data property to contain the data used to generate the graph. However, the form of the data can differ considerably from one type of graph to another. Consequently, the way each class implements the Data property can be different. The same differences apply to methods. All classes can have a draw method that creates the graph, but the implementation of this method changes with the type of graph. The basic idea of an interface class is to specify the properties and methods that each subclass must implement without defining the actual implementation. This approach enables you to enforce a consistent interface to a group of related objects. As you add more classes in the future, the original interface remains.
10-52
AxesHandle Handle of the axes used for the graph. The specialized graph objects can set axes object properties and also limit this propertys SetAccess and GetAccess to protected. Data All specialized graph objects must store data, but the type of data varies so each subclass defines the storage mechanism. Subclass users can change the data so this property has public access rights. The graph class names three abstract methods that subclasses must implement. The graph class also suggests in comments that each subclass constructor must accept the plot data and property name/property value pairs for all class properties. subclass_constructor Accept data and P/V pairs and return an object. draw Used to create a drawing primitive and render a graph of the data according to the type of graph implemented by the subclass. zoom Implementation of a zoom method by changing the axes CameraViewAngle property. The interface suggests the use of the camzoom function for consistency among subclasses. The zoom buttons created by the addButtons static method use this method as a callback. updateGraph Method called by the set.Data method to update the plotted data whenever the Data property changes.
10-53
10
10-54
The graph class implements the property set method (set.Data) to monitor changes to the Data property. An alternative is to define the Data property as Abstract and enable the subclasses to determine whether to implement a set access method for this property. However, by defining the set access method that calls an abstract method (updateGraph, which each subclass must implement), the graph interface imposes a specific design on the whole package of classes, without limiting flexibility.
10-55
10
(graph) and subclass are all contained in a package (graphics), which you must use to reference the class name:
classdef linegraph < graphics.graph
Adding Properties
The linegraph class implements the interface defined in the graph class and adds two additional propertiesLineColor and LineType. This class defines initial values for each property, so specifying property values in the constructor is optional. You can create a linegraph object with no data, but you cannot produce a graph from that object.
properties LineColor = [0 0 0]; LineType = '-'; end
10-56
if isempty(gobj.Data) error('The linegraph object contains no data') end h = line(gobj.Data.x,gobj.Data.y,... 'Color',gobj.LineColor,... 'LineStyle',gobj.LineType); gobj.Primitive = h; gobj.AxesHandle = get(h,'Parent'); end
10-57
10
Clicking the Zoom In button shows the zoom method providing the callback for the button.
10-58
10-59
10
10-60
11
Saving and Loading Objects
The Save and Load Process on page 11-2 Modifying the Save and Load Process on page 11-6 Example Maintaining Class Compatibility on page 11-9 Passing Arguments to Constructors During Load on page 11-14 Saving and Loading Objects from Class Hierarchies on page 11-17 Saving and Loading Dynamic Properties on page 11-20 Tips for Saving and Loading on page 11-22
11
Properties that have their Transient, Constant, or Dependent attributes set to true. See Specifying Property Attributes on page 6-7 for a description of property attributes.
11-2
See Property Set Methods on page 6-14 for information on property set methods.
11-3
11
See the handle class delete method and the clear command for more information on these operations.
11-4
You must call the objects constructor with arguments and, therefore, cannot support a default constructor (no arguments).
Information to Consider
If you decide to modify the default save and load process, keep the following points in mind: If your loadobj method generates an error, MATLAB still loads the objects in whatever state the object was in before the invocation of loadobj. Subclass objects inherit superclass loadobj and saveobj methods. Therefore, if you do not implement a loadobj or saveobj method in the most specific class, MATLAB calls only the inherited methods. If a superclass implements a loadobj or saveobj method, then your subclass can also implement a loadobj or saveobj method that calls the superclass methods as necessary. See Saving and Loading Objects from Class Hierarchies on page 11-17 for more information. The load function does not call the default constructor by default. See Calling Constructor When Loading on page 11-25 for more information. If an error occurs while the object is loading from a file, the load function passes your loadobj method as much data as it can successfully load from the file. In case of an error, load passes loadobj a struct whose field names correspond to the property names extracted from the file. See Reconstructing Objects with loadobj on page 11-15 for an example of a loadobj method that processes a struct. See Tips for Saving and Loading on page 11-22 for guidelines on saving and loading objects.
11-5
11
11-6
In this case, you do not need to implement a saveobj method. You are using loadobj only to ensure older saved objects are brought up to date before loading. The Save and Load Applications on page 11-7 section provides an example in which loadobj performs specific operations to recreate an object based on the data returned by saveobj during the save operation.
11-7
11
Example Maintaining Class Compatibility on page 11-9 how to maintain compatibility among progressive versions of an application. Passing Arguments to Constructors During Load on page 11-14 using loadobj to call the class constructor of an object when you need to pass arguments to the constructor during load. Saving and Loading Objects from Class Hierarchies on page 11-17 how inherited methods affect saving and loading objects. Saving and Loading Dynamic Properties on page 11-20 how to handle dynamic properties when saving and loading objects.
11-8
11-9
11
Address PhoneNumber end methods (Static) function obj = loadobj(obj) if isstruct(obj) % Call default constructor newObj = PhoneBookEntry; % Assign property values from struct newObj.Name = obj.Name; newObj.Address = obj.Address; newObj.PhoneNumber = obj.PhoneNumber; obj = newObj; end end end methods function obj = saveobj(obj) s.Name = obj.Name; s.Address = obj.Address; s.PhoneNumber = obj.PhoneNumber; obj = s; end end end saveobj saves the object data in a struct that uses property names for field names. This struct is compatible with Version 1 of the product. When the struct is loaded into Version 2 of the phone book application program, the static loadobj method converts the struct to a PhoneBookEntry object. For example, given the previously defined struct V1: V1 = Name: 'MathWorks, Inc.' Address: '3 Apple Hill Drive, Natick, MA, 01760' PhoneNumber: '5086477000'
The application program can use the loadobj static method to convert this Version 1 struct to a Version 2 object:
11-10
V2 = PhoneBookEntry.loadobj(V1) V2 = PhoneBookEntry Properties: Name: 'MathWorks, Inc.' Address: '3 Apple Hill Drive, Natick, MA, 01760' PhoneNumber: '5086477000'
If a Version 2 PhoneBookEntry object is loaded, load automatically calls the objects loadobj method, which converts the struct to an object compatible with Version 2 of the phone book application program.
11-11
11
properties (Transient) SaveInOldFormat = 0; end methods (Static) function obj = loadobj(obj) if isstruct(obj) % Call default constructor newObj = PhoneBookEntry; % Assign property values from struct newObj.Name = obj.Name; newObj.Address = obj.Address; newObj.PhoneNumber = obj.PhoneNumber; obj = newObj; end end end methods function address = get.Address(obj) address=[obj.StreetAddress obj.Sep obj.City obj.Sep obj.State obj.Sep obj.ZipCode]; end function obj = set.Address(obj,address) addressItems = regexp(address,obj.Sep,'split'); if length(addressItems) == 4 obj.StreetAddress = addressItems{1}; obj.City = addressItems{2}; obj.State = addressItems{3}; obj.ZipCode = addressItems{4}; else error('PhoneBookEntry:InvalidAddressFormat', ... 'Invalid address format.'); end end function obj = saveobj(obj) % If set to true, save as a struct if obj.SaveInOldFormat s.Name = obj.Name; s.Address = obj.Address; s.PhoneNumber = obj.PhoneNumber; obj = s; end
11-12
end end
To maintain compatibility among all versions, Version 3 of the PhoneBookEntry class applies the following techniques: Preserve the Address property (which is used in Version 2) as a Dependent property with private SetAccess. Define an Address property get method (get.Address) to build a string that is compatible with the Version 2 Address property. The get.Address method is invoked from the saveobj method to assign the object data to a struct that is compatible with previous versions. The struct continues to have only an Address field built from the data in the new StreetAddress, City, State, and ZipCode properties. As the loadobj method sets the objects Address property, it invokes the property set method (set.Address), which extracts the substrings required by the StreetAddress, City, State, and ZipCode properties. The Transient (not saved) property SaveInOldFormat enables you to specify whether to save the Version 3 object as a struct or an object. See Property Set and Get Access Methods on page 6-12 for more on property set and get methods.
11-13
11
Example Overview
This example shows how to use loadobj to call a class constructor with arguments at load time. Because the constructor requires arguments, you cannot use the ConstructOnLoad attribute to load the object, which causes a call to the default (no arguments) constructor.
11-14
This example uses loadobj to determine the status of a BankAccountSL object when the object data is loaded, and then calls the class constructor with the appropriate arguments to create the object. This approach provides a way to modify the criteria for determining status over time, while ensuring that all loaded objects are using the current criteria. The saveobj method extracts the data from the object and writes this data into a struct, which saveobj returns to the save function.
11-15
11
function obj = loadobj(A) if A.AccountBalance > 0 obj = BankAccountSL(A.AccountNumber,A.AccountBalance,'open'); elseif else obj = BankAccountSL(A.AccountNumber,A.AccountBalance,'frozen'); end end end A.AccountBalance < 0) && (A.AccountBalance >= -100) obj = BankAccountSL(A.AccountNumber,A.AccountBalance,'overdrawn');
11-16
11-17
11
The following superclass (MySuper) and subclass (MySub) definitions show how to code these methods. The MySuper class defines a loadobj method to enable an object of this class to be loaded directly. The subclass loadobj method calls a method named reload after it constructs the subclass object. reload first calls the superclass reload method to assign superclass property values and then assigns the subclass property value.
classdef MySuper % Superclass definition properties X Y end methods function S = saveobj(obj) % Save property values in struct % Return struct for save function to write to MAT-file S.PointX = obj.X; S.PointY = obj.Y; end function obj = reload(obj,S) % Method used to assign values from struct to properties % Called by loadobj and subclass obj.X = S.PointX; obj.Y = S.PointY; end end methods (Static) function obj = loadobj(S) % Constructs a MySuper object % loadobj used when a superclass object is saved directly % Calls reload to assign property values retrived from struct % loadobj must be Static so it can be called without object obj = MySuper; obj = reload(obj,S); end end end
11-18
Your subclass implements saveobj and loadobj methods that call superclass methods.
classdef MySub < MySuper % Subclass definition properties Z end methods function S = saveobj(obj) % Call superclass saveobj % Save property values in struct S = saveobj@MySuper(obj); S.PointZ = obj.Z; end function obj = reload(obj,S) % Call superclass reload method % Assign subclass property value % Called by loadobj obj = reload@MySuper(obj,S); obj.Z = S.PointZ; end end methods (Static) function obj = loadobj(S) % Create object of MySub class % Assign property value retrived from struct % loadobj must be Static so it can be called without object obj = MySub; obj = reload(obj,S); end end end
11-19
11
If your class implements a saveobj method that converts the object to another type of MATLAB variable, such as a struct, you can save the dynamic propertys attribute values so that your loadobj method can reconstruct these properties. The attribute values of dynamic properties are not part of the class definition and might have been set after the properties were attached to the object, so these values might not be known to the loadobj method.
11-20
s.dynamicprops(1).value = obj.DynoProp; % Record additional dynamic property attributes so they can be % restored at load time, for example SetAccess and GetAccess s.dynamicprops(1).setAccess = metaDynoProp.SetAccess; s.dynamicprops(1).getAccess = metaDynoProp.GetAccess; ... end end
Your loadobj method can add the dynamic property and set the attribute values:
methods (Static) function obj = loadobj(s) % first, create an instance of the class obj = ClassConstructor; ... % Add new dynamic property to object metaDynoProp = addprop(obj,s.dynamicprops(1).name); obj.(s.dynamicprops(1).name) = s.dynamicprops(1).value; % Restore dynamic property attributes metaDynoProp.SetAccess = s.dynamicprops(1).setAccess; metaDynoProp.GetAccess = s.dynamicprops(1).getAccess; end end
11-21
11
11-22
11-23
11
obj.PrivateUnits = newUnits; end case 'km' if strcmp(obj.Units, 'mi') obj.TotalDistance = obj.TotalDistance * ... obj.ConversionFactor; obj.PrivateUnits = newUnits; end otherwise error('Odometer:InvalidUnits', ... 'Units ''%s'' is not supported.', newUnits); end end end end
Suppose you create an instance of Odometer with the following property values:
odObj = Odometer; odObj.Units = 'km'; odObj.TotalDistance = 16;
When you save the object, the following happens to property values: ConversionFactor is not saved because it is a Constant property. TotalDistance is saved. Units is not saved because it is a Dependent property. PrivateUnits is saved and provides the storage for the current value of Units. When you load the object, the following happens to property values: ConversionFactor is obtained from the class definition. TotalDistance is loaded from the saved object. Units is not loaded so its set method is not called.
11-24
PrivateUnits is loaded and contains the value that is used if the Units get method is called. If the Units property was not Dependent, loading it calls its set method and causes the TotalDistance property to be set again. See The AxesObj Class on page 9-7 for another example of a class that uses a private, non-Dependent property to isolate a public, Dependent property from load-order side effects.
11-25
11
See Passing Arguments to Constructors During Load on page 11-14 for an alternative.
11-26
12
Enumerations
Defining Named Values on page 12-2 Enumerations on page 12-4 Enumerations Derived from Built-In Classes on page 12-15 Mutable (Handle) vs. Immutable (Value) Enumeration Members on page 12-21 Enumerations That Encapsulate Data on page 12-28 Saving and Loading Enumerations on page 12-32
12
Enumerations
Constant Properties
Use constant properties when you want a collection of related constant values whose values can belong to different types (numeric values, character strings, and so on). Define properties with constant values by setting the property Constant attribute. Reference constant properties by name whenever you need access to that particular value. See for more information.
Enumerations
Use enumerations when you want to create a fixed set of names representing a single type of value. You can derive enumeration classes from other classes to inherit the operations of the superclass. For example, if you define an enumeration class that subclasses a MATLAB numeric class like double or int32, the enumeration class inherits all of the mathematical and relational operations that MATLAB defines for those classes. Using enumerations instead of character strings to represent a value, such as colors ('red'), can result in more readable code because: You can compare enumeration members with == instead of using strcmp Enumerations maintain type information, strings do not. For example, passing a string 'red' to functions means that every function must interpret what 'red' means. If you define red as an enumeration, the actual value of 'red' can change (from [1 0 0] to [.93 .14 .14], for example) without updating every function that accepts colors, as you would if you defined the color as a string 'red'.
12-2
Define enumerations by creating an enumeration block in the class definition. See Enumerations on page 12-4 for more information.
12-3
12
Enumerations
Enumerations
In this section... Basic Knowledge on page 12-4 Using Enumeration Classes on page 12-5 Defining Methods in Enumeration Classes on page 12-8 Defining Properties in Enumeration Classes on page 12-9 Array Expansion Operations on page 12-10 Constructor Calling Sequence on page 12-11 Restrictions Applied to Enumeration Classes on page 12-13 Techniques for Defining Enumerations on page 12-13
Basic Knowledge
The material presented in this section builds on an understanding of the information provided in the following sections. Chapter 3, Class DefinitionSyntax Reference , Creating Subclasses Syntax and Techniques on page 10-7, Chapter 6, Properties Storing Class Data, Chapter 7, Methods Defining Class Operations
12-4
Enumerations
Underlying value For enumerations derived from built-in classes, the value associated with an instance of an enumeration class (that is, an enumeration member).
For example, assign the enumeration member WeekDays.Tuesday to the variable today:
today = WeekDays.Tuesday; today is a variable of class WeekDays: >> whos Name today >> today today = Tuesday
Size 1x1
Bytes 56
Class WeekDays
Attributes
12-5
12
Enumerations
Default Methods
Enumeration classes have four methods by default:
>> methods(today) Methods for class WeekDays: WeekDays char eq ne
Default constructor (WeekDays in this case) char converts enumeration members to character strings eq enables use of == in expressions ne enables use of ~= in expressions Equality and inequality methods enable you to use enumeration members in if and switch statements and other functions that test for equality. Because you can define enumeration members with descriptive names, conversion to char is useful. For example:
today = WeekDays.Friday; ['Today is ',char(today)] ans = Today is Friday
12-6
Enumerations
12-7
12
Enumerations
Bytes 60 4
Attributes
The uint32 constructor accepts an instance of the subclass Bearing and returns and object of class uint32.
12-8
Enumerations
classdef WeekDays enumeration Monday, Tuesday, Wednesday, Thursday, Friday end methods function tf = isMeetingDay(obj) tf = ~(WeekDays.Tuesday == obj); end end end
12-9
12
Enumerations
methods function c = SyntaxColors(r, g, b) c.R = r; c.G = g; c.B = b; end end enumeration Error (1, 0, 0) Comment (0, 1, 0) Keyword (0, 0, 1) String (1, 0, 1) end end
When you refer to an enumeration member, the constructor initializes the property values:
e = SyntaxColors.Error; e.R ans = 1
Because SyntaxColors is a value class (it does not derive from handle), only the class constructor can set property values:
e.R = 0 ??? Setting the 'R' property of the 'SyntaxColors' class is not allowed.
See Mutable (Handle) vs. Immutable (Value) Enumeration Members on page 12-21 for more information on enumeration classes that define properties.
12-10
Enumerations
Monday, Tuesday, Wednesday, Thursday, Friday end end clear ary(5) = WeekDays.Tuesday;
MATLAB must initialize the values of array elements ary(1:4). The default value of an enumeration class is the first enumeration member defined by the class in the enumeration block. The result of the assignment to the fifth element of the array ary is, therefore:
ary ary = Monday Monday Monday Monday Tuesday
12-11
12
Enumerations
end
The values of 0 and 1 are of class logical because the default constructor passes the argument to the first superclass. That is,
n = Boolean.No;
MATLAB passes the member argument only to the first superclass. For example, suppose Boolean derived from another class:
classdef Boolean < logical & MyBool enumeration No (0) Yes (1) end end
Now, the default Boolean constructor behaves as if defined like this function:
function obj = Boolean(val) obj@logical(val) % Argument passed to first superclass constructor obj@MyBool % No arguments passed to subsequent constructors end
12-12
Enumerations
12-13
12
Enumerations
12-14
Basic Knowledge
See Classes (Data Types) for information on MATLAB built-in classes.
12-15
12
Enumerations
Because the enumeration member inherits the methods of the int32 class (not the colon operator), you can use these enumerations like numeric values (summed, sorted, averaged, and so on).
isa(Results.Second,'int32') ans = 1
For example, use enumeration names instead of numbers to rank two teams:
Team1 = [Results.First, Results.NoPoints, Results.Third, Results.Second]; Team2 = [Results.Second, Results.Third, Results.First, Results.First];
12-16
For example, the actual name of an instance of the Boolean.off enumeration member is No:
a = Boolean.No a = No
12-17
12
Enumerations
b = Boolean.off b = No
This class derives from the built-in logical class. Therefore, underlying values for an enumeration member depend only on what value logical returns when passed that value:
a = Boolean.Yes a = Yes logical(a) ans = 1
12-18
returns an instance that is the result of MATLAB calling the default constructor with the argument value of 50. MATLAB passes this argument to the first superclass constructor (int32(50) in this case), which results in an underlying value of 50 as a 32-bit integer for the FlowRate.Medium member. Because FlowRate subclasses a MATLAB built-in numeric class (int32), it cannot define properties. However FlowRate inherits int32 methods including a converter method, which programs can use to obtain the underlying value:
setFlow = FlowRate.Medium; int32(setFlow) ans = 50
Default Converter
All enumeration classes based on built-in classes have a default conversion method to convert built-in data to an enumeration member of that class. For example:
a = Boolean(1) a = Yes
An enumerated class also accepts enumeration members of its own class as input arguments:
Boolean(a)
12-19
12
Enumerations
ans = Yes
Nonscalar inputs to the converter method return an object of the same size:
Boolean([0,1]) ans = No Yes
12-20
Basic Knowledge
See Comparing Handle and Value Classes on page 5-2 for general information about these two kinds of classes.
12-21
12
Enumerations
12-22
end end enumeration Red (1, 0, 0) Green (0, 1, 0) Blue (0, 0, 1) end end
12-23
12
Enumerations
methods function c = HandleColors(r, g, b) c.R = r; c.G = g; c.B = b; end end enumeration Red (1, 0, 0) ... % Other colors omitted end end
MATLAB constructs the HandleColors.Red enumeration member, which sets the R property to 1, the G property to 0, and the B property to 0. Change the value of the R property to .8:
a.R = .8;
After setting the value of the R property to .8, create another instance, b, of HandleColors.Red:
b = HandleColors.Red; b.R ans = 0.8000
12-24
The value of the R property of the newly created instance is also 0.8000. The MATLAB session has only one value for any enumeration member at any given time. Clearing the workspace variables does not change the current definition of the enumeration member HandleColors.Red:
clear a = HandleColors.Red; a.R ans = 0.8000
Clear the class to reload the definition of the HandleColors class (see clear classes):
clear classes a = HandleColors.Red; a.R ans = 1
If you do not want to allow reassignment of a given property value, set that propertys SetAccess attribute to immutable. See Property Attributes on page 6-8 for more information about property attributes.
12-25
12
Enumerations
The property values of a and b are the same, so isequal returns true. However, unlike nonenumeration handle classes, a and b are the same handle because there is only one enumeration member. Determine handle equality using == (the handle eq method).
>> a == b ans = 1
See the handle eq method for information on how isequal and == differ when used with handles.
The Machine class represents a machine with start and stop operations. The MachineState enumerations are easy to work with because of their eq and char methods, and they result in code that is easy to read.
classdef Machine < handle properties (SetAccess = Private) State = MachineState.NotRunning; end
12-26
methods function start(machine) if machine.State == MachineState.NotRunning machine.State = MachineState.Running; end disp (machine.State.char) end function stop(machine) if machine.State == MachineState.Running machine.State = MachineState.NotRunning; end disp (machine.State.char) end end end
12-27
12
Enumerations
Representing Colors
Suppose you want to use a particular set of colors in all your graphs. You can define an enumeration class to represent the RGB values of the colors in your color set. The Colors class defines names for the colors, each of which uses the RGB values as arguments to the class constructor:
classdef Colors properties R = 0; G = 0; B = 0; end methods function c = Colors(r, g, b) c.R = r; c.G = g; c.B = b; end end enumeration Blueish (18/255,104/255,179/255) Reddish (237/255,36/255,38/255) Greenish (155/255,190/255,61/255) Purplish (123/255,45/255,116/255) Yellowish (1,199/255,0) LightBlue (77/255,190/255,238/255) end
12-28
end
Suppose you want to specify the new shade of red named Reddish:
a = Colors.Reddish; a.R ans = 0.9294 a.G ans = 0.1412 a.B ans = 0.1490
Use these values by accessing the enumeration members properties. For example, the myPlot function accepts a Colors enumeration member as an input argument and accesses the RGB values defining the color from the property values.
function h = myPlot(x,y,LineColor) % Simple plotting function h = line('XData',x,'YData',y); r = LineColor.R; g = LineColor.G; b = LineColor.B; set(h,'Color',[r g b]) end
12-29
12
Enumerations
The Colors class encapsulates the definitions of a standard set of colors. These definitions can change in the Colors class without affecting functions that use the Colors enumerations.
12-30
The CarPainter class requires its subclasses to define a method called paint:
classdef CarPainter < handle methods (Abstract) paint(carobj,colorobj) end end
12-31
12
Enumerations
Basic Knowledge
See the save and load functions and The Save and Load Process on page 11-2 for general information on saving and loading objects.
12-32
Struct Fields
The returned struct has the following fields: ValueNames A cell array of strings, one per unique value in the enumeration array. Values An array of the same dimension as ValueNames containing the corresponding values of the enumeration members named in ValueNames. Depending on the kind of enumeration class, Values can be one of the following:
If the enumeration class derives from a built-in class, the array is of the built-in class and the values in the array are the underlying values of each enumeration member. Otherwise, a struct array representing the property name property values pairs of each enumeration member. For simple and handle-based enumerations, the struct array has no fields.
12-33
12
Enumerations
ValueIndices a uint32 array of the same size as the original enumeration. Each element is an index into the ValueNames and Values arrays. The content of ValueIndices represents the value of each object in the original enumeration array.
12-34
13
Constant Properties
13
Constant Properties
MATLAB evaluates the expressions when loading the class (when you first reference a constant property from that class). Therefore, the values MATLAB assigns to RN are the result to a single call to the rand function and do not change with subsequent references to NamedConst.RN. Calling clear classes causes MATLAB to reload the class.
13-2
For example, to use the RadDeg class defined in the previous section, reference the constant for the degree to radian conversion, R:
radi = 45*RadDeg.R radi = 0.7854
The class defines a set of Constant properties with initial values assigned:
classdef AstroConstants properties (Constant) C = 2.99792458e8; % m/s G = 6.67259; % m/kgs Me = 5.976e24; % Earth mass (kg) Re = 6.378e6; % Earth radius (m) end end
To use this set of constants, reference them with a fully qualified class name. For example, the following function uses some of the constants defined in AstroContants:
function E = energyToOrbit(m,r) E = Constants.AstroConstants.G * Constants.AstroConstants.Me * m * ...
13-3
13
Constant Properties
(1/Constants.AstroConstants.Re-0.5*r); end
You cannot import class properties. Therefore, use the fully qualified class name to reference constant properties.
13-4
1.0e+003 * 2.0090 0.0070 0.0080 clear classes MyCnstClass.Instance.Date ans = 1.0e+003 * 2.0090 0.0070 0.0080 0.0110 0.0450 0.0419 0.0110 0.0440 0.0331
For properties that are not Constant, you cannot use a class instance for a default value.
13-5
13
Constant Properties
13-6
14
Obtaining Information About Classes from Meta-Classes
Working with Meta-Classes on page 14-2 Using Meta-Classes to Inspect Classes and Objects on page 14-4 Finding Objects Having Specific Settings on page 14-7 Getting Information About Properties on page 14-10 Getting Property Default Values on page 14-17
14
Each meta-class has properties, methods, and events that contain information about the class or class component. See meta.package, meta.class, meta.property, meta.method and meta.event for more information on these meta-classes.
14-2
meta.class.fromName('ClassName') returns the meta.class object for the named class (meta.class.fromName is a meta.class method). metaclass(obj) Returns a meta-class object for the class instance (metaclass)
% create meta-class object from class name using the ? operator mobj = ?classname; % create meta-class object from class name using the fromName method mobj = meta.class.fromName('classname'); % create meta-class object from class instance obj = myClass; mobj = metaclass(obj);
The metaclass function returns the meta.class object (that is, an object of the meta.class class). You can obtain other meta-class objects (meta.property, meta.method, and so on) from the meta.class object. Note Meta-class is a term used here to describe a kind of class. meta.class is a class in the meta package whose instances contain information about MATLAB classes.
14-3
14
Inspecting a Class
The EmployeeData class is a handle class with two properties, one of which has private Access and defines a set access method.
classdef EmployeeData < handle properties EmployeeName end properties (Access = private) EmployeeNumber end methods function obj = EmployeeData(name,ss) if nargin > 0 obj.EmployeeName = name; obj.EmployeeNumber = ss; end end function set.EmployeeName(obj,name) if ischar(name) obj.EmployeeName = name; else error('Employee name must be a text string') end end end end
14-4
mc = ?EmployeeData;
Inspecting Properties
Find the names of the properties defined by this class. First obtain a cell array of meta.properties objects from the meta.class Properties property.
mpCell = mc.Properties;
The length of mpCell indicates there are two meta.property objects, one for each property defined by the EmployeeData class:
length(mpCell) ans = 2
The Name property of the meta.property object identifies the class property represented by that meta.property object. Query other meta.property object properties to determine the attributes of the EmployeeName property.
14-5
14
mpCell = mcEdObj.Properties; EdObj.(mpCell{1}.Name) % Dynamic field names work with objects ans = My Name EdObj.(mpCell{2}.Name) ??? Getting the 'EmployeeNumber' property of the 'EmployeeData' class is not allowed. mpCell{2}.GetAccess ans = private
14-6
14-7
14
The -property option enables you to omit the value of the property and search for objects using only the property name.
14-8
The cell array names contains the names of all containers.Map properties that have public GetAccess:
celldisp(names) names{1} = Count names{2} = KeyType names{3} = ValueType
14-9
14
14-10
The preceding meta.property display shows that the default Map object Count property has public GetAccess and private SetAccess, is Dependent, and Transient. See Table of Property Attributes on page 6-8 for a list of property attributes. If you are working with a class that is not a handle class, get the meta.property objects from the meta.class object. All meta-classes are subclasses of the handle class. Use the metaclass function if you have an instance or the ? operator with the class name:
mc = ?containers.Map mc = meta.class handle Package: meta Properties: Name: Description: DetailedDescription: Hidden: Sealed: ConstructOnLoad: InferiorClasses: Properties: Methods: Events: EnumeratedValues: SuperClasses: ContainingPackage: 'containers.Map' 'MATLAB Map Container' 'MATLAB Map Container' 0 0 1 {0x1 cell} {4x1 cell} {33x1 cell} {[1x1 meta.event]} {0x1 cell} {[1x1 meta.class]} [1x1 meta.package]
The meta.class object property named Properties contains a cell array of meta.property objects, one for each property defined by the containers.Map class. For example, the name of the property associated with the meta.property object in cell 1 is:
14-11
14
The meta.class object contains a meta.property object for hidden properties too. Compare the result with the properties function, which returns only public properties:
properties('containers.Map') Properties for class containers.Map: Count KeyType ValueType
The serialization property is Hidden and has its GetAccess and SetAccess attributes set to private. Therefore, the properties function does not list it. However, you can get information about this property from its associated meta.property object (which is the fourth element in the cell array of meta.property objects in this case):
mc.Properties{4} ans = meta.property handle Package: meta Properties: Name: Description: DetailedDescription: GetAccess: SetAccess: Dependent: Constant: Abstract: Transient: 'serialization' 'Serialization property.' '' 'private' 'private' 0 0 0 0
14-12
1 0 0 0 [] [] [1x1 meta.class]
Referencing the Properties meta.class property returns a cell array with one cell for each property of the containers.Map class:
class(mc.Properties) ans = cell
14-13
14
The Name property of the meta.property object contains a character string that is the name of the property:
class(mc.Properties{1}.Name) ans = char
Apply standard MATLAB indexing to access information in meta-class objects. For example, the meta.class Properties property contains a cell array of meta.property objects. The following expression accesses the first meta.property object in this cell array and returns the first (C) and last (t) letters of the string contained in the meta.property Name property.
mc.Properties{1}.Name([1 end]) ans = Ct
14-14
Use the handle class findprop method to determine if the requested property attribute is a valid attribute name. All property attributes are properties of the meta.property object. The statement, findobj(mp,'PropertyName') determines whether the meta.property object, mp, has a property called PropertyName. Reference meta.property object properties using dynamic field names. For example, if attrName = 'Constant', then MATLAB converts the expression mp.(attrName) to mp.Constant The optional third argument enables you to specify the value of attributes whose values are not logical true or false (such as GetAccess and SetAccess).
function cl_out = findAttrValue(obj,attrName,varargin) % Determine if first input is object or class name if ischar(obj) mc = meta.class.fromName(obj); elseif isobject(obj) mc = metaclass(obj); end % Initialize and preallocate ii = 0; numb_props = length(mc.Properties); cl_array = cell(1,numb_props); % For each property, check the value of the queried attribute for c = 1:numb_props % Get a meta.property object from the meta.class object mp = mc.Properties{c}; % Determine if the specified attribute is valid on this object if isempty (findprop(mp,attrName)) error('Not a valid attribute name') end attrValue = mp.(attrName); % If the attribute is set or has the specified value, % save its name in cell array
14-15
14
if attrValue if islogical(attrValue) || strcmp(varargin{1},attrValue) ii = ii + 1; cl_array(ii) = {mp.Name}; end end end % Return used portion of array cl_out = cl_array(1:ii); end
14-16
14-17
14
HasDefault True if class specifies a default value for the property, false if it does not. DefaultValue Contains the default value, if the class defines a default value for the property. These properties provide a programmatic way to obtain property default values without reading class definition files. Use these meta.property object properties to obtain property default values for built-in classes and classes defined in MATLAB code.
14-18
Follow these steps to obtain the default value defined for the Material property. Include any error checking that is necessary for your application. Get the meta.class object for the class:
mc = ?MyClass;
Get a cell array of meta.property objects from the meta.class Properties property:
mp = mc.Properties;
The length of the cell array, mp, equals the number of properties. You can use the meta.property Name property to find the property of interest:
for k = 1:length(mp) if (strcmp(mp{k}.Name,'Material')
Before querying the default value of the Material property, test the HasDefault meta.property to determine if MyClass defines a default property for this property:
if mp{k}.HasDefault dv = mp{k}.DefaultValue; end end end
The DefaultValue property is read only. Changing the default value in the class definition changes the value of DefaultValue property. You can query the default value of a property regardless of its access settings. Abstract and dynamic properties cannot define default values. Therefore, MATLAB returns an error if you attempt to query the default value of properties with these attributes. Always test the logical value of the meta.property HasDefault property before querying the DefaultValue property to avoid generating an error.
14-19
14
information). MATLAB evaluates these expressions the first time the default value is needed, such as the first time you create an instance of the class. Querying the meta.property DefaultValue property causes MATLAB to evaluate a default value expression, if it had not yet been evaluated. Therefore, querying a property default value can return an error or warning if errors or warnings occur when MATLAB evaluates the expression. See Property With Expression That Errors on page 14-21 for an example.
The meta.property instance for property Foo has a value of false for HasDefault. The class does not explicitly define a default value for Foo. Therefore, attempting to access the DefaultValue property causes an error:
mc = ?MyClass; mp = mc.Properties{1}; mp.HasDefault ans = 0 dv = mp.DefaultValue; ??? No default value has been defined for property Foo
Abstract Property
MyClass defines the Foo property as Abstract: classdef MyClass properties (Abstract) Foo end
14-20
end
The meta.property instance for property Foo has a value of false for its HasDefault property because you cannot define a default value for an Abstract property. Attempting to access DefaultValue causes an error:
mc = ?MyClass; mp = mc.Properties{1}; mp.HasDefault ans = 0 dv = mp.DefaultValue; ??? Property Foo is abstract and therefore cannot have a default value.
The meta.property instance for property Foo has a value of true for its HasDefault property because Foo does have a default value determined by the evaluation of the expression:
sin(pie/2)
However, this expression returns an error (pie is a function that creates a pie chart, not the value pi).
mc = ?MyClass; mp = mc.Properties{1}; mp.HasDefault ans = 1
14-21
14
dv = mp.DefaultValue; ??? Error using ==> pie at 30 Not enough input arguments.
Querying the default value causes the evaluation of the expression and returns the error.
The meta.property instance for property Foo has a value of true for its HasDefault property. Accessing DefaultValue returns the value []:
mc = ?MyClass; mp = mc.Properties{1}; mp.HasDefault ans = 1 dv = mp.DefaultValue; dv = []
14-22
15
Specializing Object Behavior
Methods That Modify Default Behavior on page 15-2 Redefining Concatenation for Your Class on page 15-8 Displaying Objects in the Command Window on page 15-9 Converting Objects to Another Class on page 15-11 Indexed Reference and Assignment on page 15-13 Implementing Operators for Your Class on page 15-35
15
Description Customize behavior when concatenation objects See Example Adding Properties to a Built-In Subclass on page 10-35
Displaying Objects
15-2
Description Called when you enter disp(obj) on the command line Called when statements are not terminated by semicolons. disp is often used to implement display methods. See Displaying Objects in the Command Window on page 15-9
Convert an object to a MATLAB built-in class See The DocPolynom to Character Converter on page 16-8 and The DocPolynom to Double Converter on page 16-7
Indexing Objects
subsref and subsasgn
Enables you to create nonstandard indexed reference and indexed assignment See Indexed Reference and Assignment on page 15-13
end
Determine the number of elements in an array See Interactions with numel and Overloaded subsref and subsasgn on page 15-6
size
15-3
15
Description Support using an object in indexing expressions See Using Objects as Indices on page 15-32
Customize behavior when loading and saving objects See Chapter 11, Saving and Loading Objects
See Implementing Operators for Your Class on page 15-35 for a list of functions that implement operators like +, >, ==, and so on.
Overloading
Overloading means that there is more than one function or method that have the same name within the same scope. MATLAB dispatches to a particular function or method based on the dominant argument. For example, the timeseries class overloads the MATLAB plot function. When you call plot with a timeseries object as an input argument, MATLAB dispatches to the timeseries class method named plot. MATLAB
15-4
Overriding
Overriding means redefining a method inherited from a superclass. MATLAB dispatches to the most specific version of the method. That is, if the dominant argument is an instance of the subclass, then MATLAB calls the subclass method.
as a reference to the third element in the array p. However, suppose you define a class to represent polynomials and you want an indexed reference like:
polyobj(3)
to cause an evaluation of the scalar polynomial object with the value of the independent variable equal to the index value, 3. You overload the subsref function for the polynomial class to accomplish this. See The DocPolynom subsref Method on page 16-11 for an example. Select the appropriate function from the preceding table to change the behavior indicated. For example, MATLAB displays certain information about objects when you use the disp function or when you enter a statement that returns an object and is not terminated by a semicolon. Suppose you want your polynomial class to display the MATLAB expression for the polynomial represented by the object, instead of the default behavior. The display might look like this:
>> p
15-5
15
p = x^3 - 2*x - 5
for a polynomial with the coefficients [1 0 2 -5]. You can implement this specialized behavior by overloading the disp and char methods. See The DocPolynom disp Method on page 16-10 for an example that shows how to implement this change.
15-6
See Understanding size and numel on page 10-41 and Indexed Reference and Assignment on page 15-13 for more information on implementing subsref and subsagn methods.
See Determining Which Method Is Invoked on page 7-8 for more information.
15-7
15
You can overload horzcat, vertcat, and cat to produce specialized behaviors in your class. You must overload both horzcat and vertcat whenever you want to modify object concatenation because MATLAB uses both functions for any concatenation operation.
15-8
All MATLAB objects use default disp and display functions. You do not need to overload the defaults, but you can overload in cases where you want objects to display in different ways. You can define a disp method for your classes if you want MATLAB to display more useful information on the command line when referring to objects from your class. In many classes, disp can print the variable name, and then use the char converter method to print the contents of the variable. You need to define the char method to convert the objects data to a character string because MATLAB displays output as character strings. You might also use sprintf or other data formatting functions to implement the disp method for your class.
15-9
15
15-10
coefficients of a polynomial.
MATLAB software compares the class of the Right-Hand-Side (RHS) variable to the class of the Left-Hand-Side (LHS) variable. If the classes are different, MATLAB attempts to convert the RHS variable to the class of the LHS
15-11
15
variable. To do this, MATLAB first searches for a method of the RHS class that has the same name as the LHS class. Such a method is a converter method, which is similar to a typecast operation in other languages. If the RHS class does not define a method to convert from the RHS class to the LHS class, then MATLAB software calls the LHS class constructor and passes it to the RHS variable. For example, suppose you make the following assignments:
A(1) = objA; % Object of class ClassA A(2) = objB; % Object of class ClassB
MATLAB attempts to call a method of ClassB named ClassA. If no such converter method exists, MATLAB software calls the ClassA constructor, passing objB as an argument. If the ClassA constructor cannot accept objB as an argument, then MATLAB returns an error. You can create arrays of objects of different classes using cell arrays (see cell for more information on cell arrays).
15-12
Overview
This section describes how indexed reference and assignment work in MATLAB, and provides information on the behaviors you can modify. There are also examples of classes that modify the default indexing behavior. MATLAB provides support for object array indexing by default and many class designs will require no modification to this behavior. The information in this section can help you determine if modifying object indexing is useful for your class design and can show you how to approach those modifications.
15-13
15
You can reference and assign elements of either array using index values in parentheses:
B(2) = A(3,4); B B = 3 2
MATLAB calls the built-in subsref function to determine how to interpret the statement. Similarly, if you execute a statement that involves indexed assignment:
C(4) = 7;
MATLAB calls the built-in subsasgn function to determine how to interpret the statement. The MATLAB default subsref and subsasgn functions also work with user-defined objects. For example, suppose you want to create an array of objects of the same class:
for k=1:3 objArray(k) = MyClass; end
Referencing the second element in the object array, objArray, returns the object constructed when k = 2:
D = objArray(2);
15-14
You also can assign an object to an array of objects of the same class, or an empty array (see Creating Empty Arrays on page 8-6 for related information):
emptyArray(3,4) = D;
Arrays of objects behave much like numeric arrays in MATLAB. You do not need to implement any special methods to provide this behavior with your class. For general information about array indexing, see Matrix Indexing.
15-15
15
returns the value contained in the second row, third column of the array. If you have an array of objects, you can use an expression like:
objArray(3).Data(4:end)
to return the fourth through last elements in the array contained in the Data property of the third object in the object array, objArray. Modify the default indexing behavior when your class design requires behavior that is different from that provided by MATLAB by default.
calls the built-in subsref function. To call the class-defined subsref method, use:
% Calls overloaded subsref subsref(obj,substruct('.','Prop'))
15-16
Whenever a class method requires the functionality of the class-defined subsref or subsasgn method, it must call the overloaded methods with function calls rather than using the operators, '()', '{}', or '.'. For example, suppose you define a polynomial class with a subsref method that causes the polynomial to be evaluated with the value of the independent variable equal to the subscript. This statement defines the polynomial with its coefficients:
p = polynom([1 0 -2 -5]);
Suppose that you want to use this feature in another class method. To do so, call the subsref function directly. The evalEqual method accepts two polynom objects and a value at which to evaluate the polynomials:
methods function ToF = evalEqual(p1,p2,x) % Create arguments for subsref subs.type = '()'; subs.subs = {x}; % Need to call subsref explicity y1 = subsref(p1,subs); y2 = subsref(p2,subs); if y1 == y2 ToF = true; else ToF = false; end end end
15-17
15
This behavior enables you to use standard MATLAB indexing to implement specialized behaviors. See A Class with Modified Indexing on page 15-26 for examples of how to use both built-in and class-modified indexing.
Each of these statements causes a call by MATLAB to the subsref method of the class of A, or a call to the built-in subsref function, if the class of A does not implement a subsref method. MATLAB passes two arguments to subsref:
B = subsref(A,S)
The first argument is the object being referenced, A. The second argument, S, is a struct array with two fields: S.type is a string containing '()', {}', or '.' specifying the indexing type used. S.subs is a cell array or string containing the actual index or name. A colon used as an index is passed in the cell array as the string ':'. Ranges specified using a colon (e.g., 2:5) are expanded to 2 3 4 5. For example, the expression
A(1:4,:)
15-18
Returning the contents of each cell of S.subs gives the index values for the first dimension and a string ':' for the second dimension:
S.subs{:} ans = 1 ans = : 2 3 4
The default subsref returns all array elements in rows 1 through 4 and all of the columns in the array. Similarly, the expression
A{1:4}
uses
S.type ='{}' S.subs = {1:4} % A cell array % containing the numbers 1 2 3 4
The default subsref returns the contents of all cell array elements in rows 1 through 4 and all of the columns in the array. The expression
A.Name
The default subsref returns the contents of the Name field in the struct array or the value of the property Name if A is an object with the specified property name.
15-19
15
Writing subsref
Your classs subsref method must interpret the indexing expressions passed in by MATLAB. Any behavior you want your class to support must be implemented by your subsref. However, your method can call the built-in subsref to handle indexing types that you do not want to change. You can use a switch statement to determine the type of indexing used and to obtain the actual indices. The following three code fragments illustrate how to interpret the input arguments. In each case, the function must return the value (B) that is returned by your subsref function. For a parentheses index:
% Handle A(n) switch S.type case '()' B = A(S.subs{:}); end
15-20
While braces are used for cell arrays in MATLAB, your subsref method is free to define its own meaning for this syntax. For a name index, you might access property values. Method calls require a second level of indexing if there are arguments. The name can be an arbitrary string for which you take an arbitrary action:
switch S.type case '.' switch S.subs case 'name1' B = A.name1; case 'name2' B = A.name2; end end
Examples of subsref
These links show examples of classes that implement subsref methods: A Class with Modified Indexing on page 15-26 Example Adding Properties to a Built-In Subclass on page 10-35 Example A Class to Represent Hardware on page 10-46 The DocPolynom subsref Method on page 16-11 See also, Understanding size and numel on page 10-41
15-21
15
properties (Access = private) x y end properties Maximum Minimum Average end methods function obj = MyPlot(x,y) obj.x = x; obj.y = y; obj.Maximum = max(y); obj.Minimum = min(y); obj.Average = mean(y); end function B = subsref(A,S) switch S(1).type case '.' switch S(1).subs case 'plot' % Reference to A.x and A.y call built-in subsref B = plot(A.x,A.y); otherwise % Enable dot notation for all properties and methods B = A.(S.subs); end end end end end
This subsref enables users to use dot notation to perform an action (create a plot) using the name 'plot'. The statement:
obj = MyPlot(1:10,1:10); h = obj.plot;
calls the plot function and returns the handle to the graphics object.
15-22
You do not need to explicitly code each method and property name because the otherwise code in the inner switch block handles any name reference that you do not explicitly specify in case statements. However, using this technique exposes any private and protected class members via dot notation. For example, you can reference the private property, x, with this statement:
obj.x ans = 1 2 3 4 5 6 7 8 9 10
The same issue applies to writing a subsasgn method that enables assignment to private or protected properties. Your subsref and subsasgn methods might need to code each specific property and method name explicitly to avoid violating the class design.
Each of these statements causes a call by MATLAB to the subsasgn method of the class of A, or a call to the built-in function, if the class of A does not implement a subsasgn method. MATLAB passes three arguments to subsasgn:
A = subsasgn(A,S,B)
The first argument, A, is the object being assigned the value in the third argument B. The second argument, S, is a struct array with two fields:
15-23
15
S.type is a string containing '()', '{}', or '.' specifying the indexing type used. S.subs is a cell array or string containing the actual index or name. A colon used as an index is passed in the cell array as the string ':'. Ranges specified using a colon (e.g., 2:5) are expanded to 2 3 4 5. For example, the assignment statement:
A(2,3) = B;
The default subsasgn: Determines the class of A. If B is not the same class a A, then MATLAB tries to construct an object of the same class as A using B as an input argument (e.g., by calling a converter method, if one exists). If this attempt fails, MATLAB returns an error. If A and B are, or can be made, into the same class, then MATLAB assigns the value of B to the array element at row 2, column 3. If A does not exist before you execute the assignment statement, then MATLAB initializes the five array elements that come before A(2,3) with a default object of the class of A and B. For example, empty elements are initialized to zero in the case of a numeric array or an empty cell ([]) in the case of cell arrays. See Creating Empty Arrays on page 8-6 for more information on how MATLAB initializes empty arrays. Similarly, the expression
A{2,3} = B
uses
S.type ='{}' S.subs = {2,3} % A 2-element cell array containing the numbers 2 and 3
15-24
Assigns B to the cell array element at row 2, column 3. If A does not exist before you execute the assignment statement, MATLAB initializes the five cells that come before A(2,3) with []. The result is a 2by3 cell array. The expression
A.Name = B
The default subsasgn: Assigns B to the struct field Name. If A does not exist before you execute the assignment statement, MATLAB creates a new struct variable, A with field Name and assigns the value of B to this field location. If struct A exists, but has no field Name, then MATLAB adds the field Name and assigns the value of B to the new field location. If struct A exists and has a Name field, then MATLAB assigns the value of B to Name. You can redefine all or some of these assignment behaviors by implementing a subsasgn method for your class.
15-25
15
The default subsasgn: Attempts to assign B to the Name property. If the class of A does not have a Name property, MATLAB returns an error. If the Name property has restricted access (private or protected), MATLAB determines if the assignment is allowed based on the context in which the assignment is made. If the class of A defines a set method for property Name, MATLAB calls the set method. MATLAB applies all other property attributes before determining whether to assigning B to the property Name.
For examples of subsasgn methods, see Specialized Subscripted Assignment subsasgn on page 15-29 and .
15-26
Class Description
The class has three properties: Data numeric test data Description description of test data Date date test was conducted Assume you have the following data (randi):
d = randi(9,3,4) d = 8 9 2 9 6 1 3 5 9 9 2 9
The constructor arguments pass the values for the Data and Description properties. The clock function assigns the value to the Date property from within the constructor. This approach captures the time and date information when the instance is created. Here is the basic code listing without the subsref and subsasgn methods.
classdef MyDataClass properties Data Description end properties (SetAccess = private) Date end methods function obj = MyDataClass(data,desc) if nargin > 0 obj.Data = data; end
15-27
15
if nargin > 1 obj.Description = desc; end obj.Date = clock; end end end
which the class also supports. Redefining '()' indexing as described here means you cannot create arrays of MyDataClass objects and use '()' indexing to access individual objects. Create only scalar objects. To achieve the design goals, the subsref method calls the builtin subsref for indexing of type '.' and defines its own version of '()' type indexing.
function sref = subsref(obj,s) % obj(i) is equivalent to obj.Data(i) switch s(1).type % Use the built-in subsref for dot notation case '.' sref = builtin('subsref',obj,s); case '()' if length(s)<2 % Note that obj.Data is passed to subsref
15-28
sref = builtin('subsref',obj.Data,s); return else sref = builtin('subsref',obj,s); end % No support for indexing using '{}' case '{}' error('MYDataClass:subsref',... 'Not a supported subscripted reference') end end
is equivalent to:
obj.Data(2,3) = 9;
Like the subsref method, the subsasgn method calls the builtin subsasgn for indexing of type '.' and defines its own version of '()' type indexing. Another useful approach is the use of the substruct function to redefine the index type and index subscripts struct that MATLAB passes to subsref and subsasgn.
function obj = subsasgn(obj,s,val) if isempty(s) && strcmp(class(val),'MYDataClass') obj = MyDataClass(val.Data,val.Description); end switch s(1).type % Use the built-in subsasagn for dot notation case '.' obj = builtin('subsasgn',obj,s,val); case '()' if length(s)<2
15-29
15
if strcmp(class(val),'MYDataClass') error('MYDataClass:subsasgn',... 'Object must be scalar') elseif strcmp(class(val),'double') % Redefine the struct s to make the call: obj.Data(i) snew = substruct('.','Data','()',s(1).subs(:)); obj = subsasgn(obj,snew,val); end end % No support for indexing using '{}' case '{}' error('MYDataClass:subsasgn',... 'Not a supported subscripted assignment') end end
15-30
obj + 7 ans = 15 16 9 16 13 8 10 12 16 16 9 16
The MyDataClass double method provides a way to convert an object to an array of doubles. It is possible to add a MyDataClass object to another class of object, providing the other class implements a double method that also returns an array of doubles. MATLAB applies the rules of addition and returns errors for dimension mismatch, and so on.
where A is the object k is the index in the expression using the end syntax n is the total number of indices in the expression ind is the index value to use in the expression For example, consider the expression
A(end-1,:)
15-31
15
MATLAB calls the end method defined for the object A using the arguments
ind = end(A,1,2)
These arguments mean the end statement occurs in the first index element and there are two index elements. The end class method returns the index value for the last element of the first dimension (from which 1 is subtracted in this case). If your class implements an end method, ensure that it returns a value appropriate for the class.
and so on. The following end function determines a positive integer value for end and returns it so that MATLAB can plug it into the indexing expression.
function ind = end(obj,k,n) szd = size(obj.Data); if k < n ind = szd(k); else ind = prod(szd(k:end)); end end
15-32
Indexing expressions like X(A), where A is an object, cause MATLAB to call the default subsindex function, unless such an expression results in a call to an overloaded subsref or subsasgn method defined by the class of X. See Scenarios for Implementing Objects as Indices on page 15-33.
subsindex must return the value of the object as a zero-based integer index values in the range 0 to prod(size(X))-1).
Implementing subsindex
MATLAB calls the subsindex method defined for the object used as the index. For example, suppose you want to use object A to index into object B. B can be a single object or an array, depending on your objectives.
C = B(A);
A subsindex method implemented by class A might do something as simple as convert the object to double format to be used as an index, as shown in this sample code.
function ind = subsindex(obj) % Convert the object a to double format to be used % as an index in an indexing expression ind = double(obj);
15-33
15
end
Or, your class might implement a special converter method that returns a numeric value representing an object based on particular values of object properties.
function ind = subsindex(obj) % Return the value of an object property ind = obj.ElementPosition; end subsindex values are 0-based, not 1-based.
15-34
Overloading Operators
You can implement MATLAB operators (+, *, >, etc.) to work with objects of your class. Do this by defining the relevant functions as class methods. Each built-in MATLAB operator has an associated function (e.g., the + operator has an associated plus.m function). You can overload any operator by creating a class method with the appropriate name. Overloading enables operators to handle different types and numbers of input arguments and perform whatever operation is appropriate for the highest precedence object.
Object Precedence
User-defined classes have a higher precedence than built-in classes. For example, if q is an object of class double and p is a user-defined class, MyClass, both of these expressions:
q + p p + q
generate a call to the plus method in the MyClass, if it exists. Whether this method can add objects of class double and class MyClass depends on how you implement it. When p and q are objects of different classes, MATLAB applies the rules of precedence to determine which method to use. Object Precedence in Expressions Using Operators on page 7-29 provides information on how MATLAB determines which overloaded method to call.
15-35
15
Method to Define
plus(a,b) minus(a,b) uminus(a) uplus(a) times(a,b) mtimes(a,b) rdivide(a,b) ldivide(a,b) mrdivide(a,b) mldivide(a,b) power(a,b) mpower(a,b) lt(a,b) gt(a,b) le(a,b) ge(a,b) ne(a,b) eq(a,b)
Description Binary addition Binary subtraction Unary minus Unary plus Element-wise multiplication Matrix multiplication Right element-wise division Left element-wise division Matrix right division Matrix left division Element-wise power Matrix power Less than Greater than Less than or equal to Greater than or equal to Not equal to Equality
15-36
Operation
a & b a | b ~a a:d:b a:b a' a.' command window output [a b] [a; b] a(s1,s2,...sn) a(s1,...,sn) = b b(a)
Method to Define
and(a,b) or(a,b) not(a) colon(a,d,b) colon(a,b) ctranspose(a) transpose(a) display(a) horzcat(a,b,...) vertcat(a,b,...) subsref(a,s) subsasgn(a,s,b) subsindex(a)
Description Logical AND Logical OR Logical NOT Colon operator Complex conjugate transpose Matrix transpose Display method Horizontal concatenation Vertical concatenation Subscripted reference Subscripted assignment Subscript index
15-37
15
15-38
16
Implementing a Class for Polynomials
16
16-2
To use the class, create a folder named @DocPolynom and save DocPolynom.m to this folder. The parent folder of @DocPolynom must be on the MATLAB path.
Class
double
Default
[]
The following table summarizes the methods for the DocPolynom class. DocPolynom Class Methods Name
DocPolynom double char disp subsref
Description Class constructor Converts a DocPolynom object to a double (i.e., returns its coefficients in a vector) Creates a formatted display of the DocPolynom object as powers of x and is used by the disp method Determines how MATLAB displays a DocPolynom objects on the command line Enables you to specify a value for the independent variable as a subscript, access the coef property with dot notation, and call methods with dot notation. Implements addition of DocPolynom objects
plus
16-3
16
Description Implements subtraction of DocPolynom objects Implements multiplication of DocPolynom objects Overloads the roots function to work with DocPolynom objects Overloads the polyval function to work with DocPolynom objects Overloads the diff function to work with DocPolynom objects Overloads the plot function to work with DocPolynom objects
The DocPolynom disp method displays the polynomial in MATLAB syntax. Find the roots of the polynomial using the overloaded root method.
>> roots(p1) ans =
16-4
Add the two polynomials p1 and p2. The MATLAB runtime calls the plus method defined for the DocPolynom class when you add two DocPolynom objects.
p1 + p2 ans = 2*x^4 + x^3 + 3*x^2 - 12
The sections that follow describe the implementation of the methods illustrated here, as well as other methods and implementation details.
16-5
16
Input argument is a coefficient vector If the input argument is not a DocPolynom object, the constructor attempts to reshape the values into a vector and assign them to the coef property. The coef property set method restricts property values to doubles. See Removing Irrelevant Coefficients on page 16-6 for a description of the property set method. An example use of the DocPolynom constructor is the statement:
p = DocPolynom([1 0 -2 -5]) p = x^3 - 2*x -5
This statement creates an instance of the DocPolynom class with the specified coefficients. Note how class methods display the equivalent polynomial using MATLAB language syntax. The DocPolynom class implements this display using the disp and char class methods.
16-6
See Property Set Methods on page 6-14 for more information on controlling property values.
the statement:
c = double(p)
returns:
c=
16-7
16
-2
-5
16-8
else s(ind) = {' - '}; a = -a; ind = ind + 1; end end if a ~= 1 || d == 0 if a == -1 s(ind) = {'-'}; ind = ind + 1; else s(ind) = {num2str(a)}; ind = ind + 1; if d > 0 s(ind) = {'*'}; ind = ind + 1; end end end if d >= 2 s(ind) = {['x^' int2str(d)]}; ind = ind + 1; elseif d == 1 s(ind) = {'x'}; ind = ind + 1; end end d = d - 1; end end str = [s{:}]; end
16-9
16
char(p)
The value returned by char is a string that you can pass to eval after you have defined a scalar value for x. For example:
x = 3; eval(char(p)) ans = 16
The DocPolynom subsref Method on page 16-11 describes a better way to evaluate the polynomial.
16-10
p = DocPolynom([1 0 -2 -5])
creates a DocPolynom object. Since the statement is not terminated with a semicolon, the resulting output is displayed on the command line:
p = x^3 - 2*x - 5
See Displaying Objects in the Command Window on page 15-9 for information about defining the display of objects.
a subscripted reference evaluates f(x), where x is the value of the subscript. Creating a DocPolynom object p:
p = DocPolynom([1 0 -2 -5]) p = x^3 - 2*x - 5
the following subscripted expression evaluates the value of the polynomial at x = 3 and x = 4 and returns a vector of resulting values:
p([3 4]) ans = 16 51
16-11
16
This method requires an input argument of values at which to evaluate the polynomial and returns the value of f(x) at these values. subsref performs the method call through the statements:
if length(s)>1 b = a.(s(1).subs)(s(2).subs{:}); % method with arguments else b = a.(s.subs); % method without input arguments
16-12
end
When you implement a subsref method for a class, you must implement all subscripted reference explicitly, as show in the following code listing.
function b = subsref(a,s) % Implement a special subscripted assignment switch s(1).type case '()' ind = s.subs{:}; b = a.polyval(ind); case '.' switch s(1).subs case 'coef' b = a.coef; case 'plot' a.plot; otherwise if length(s)>1 b = a.(s(1).subs)(s(2).subs{:}); else b = a.(s.subs); end end otherwise error('Specify value for x as obj(x)') end end
16-13
16
When overloading arithmetic operators, keep in mind what data types you want to operate on. In this section, the plus, minus, and mtimes methods are defined for the DocPolynom class to handle addition, subtraction, and multiplication on DocPolynom/DocPolynom and DocPolynom/double combinations of operands.
generates a call to a function @DocPolynom/plus, unless the other object is of a class of higher precedence. Object Precedence in Expressions Using Operators on page 7-29 provides more information. The following function redefines the plus (+) operator for the DocPolynom class:
function r = plus(obj1,obj2) % Plus Implement obj1 + obj2 for DocPolynom obj1 = DocPolynom(obj1); obj2 = DocPolynom(obj2); k = length(obj2.coef) - length(obj1.coef); r = DocPolynom([zeros(1,k) obj1.coef]+[zeros(1,-k) obj2.coef]);
16-14
end
Here is how the function works: Ensure that both input arguments are DocPolynom objects so that expressions such as
p + 1
that involve both a DocPolynom and a double, work correctly. Access the two coefficient vectors and, if necessary, pad one of them with zeros to make both the same length. The actual addition is simply the vector sum of the two coefficient vectors. Call the DocPolynom constructor to create a properly typed result.
16-15
16
% MTIMES Implement obj1 * obj2 for DocPolynoms obj1 = DocPolynom(obj1); obj2 = DocPolynom(obj2); r = DocPolynom(conv(obj1.coef,obj2.coef)); end
The following two arithmetic operations call the DocPolynom plus and mtimes methods:
q = p+1 r = p*q
to produce
q = x^3 - 2*x - 4 r = x^6 - 4*x^4 - 9*x^3 + 4*x^2 + 18*x + 20
16-16
MATLAB Function
root(obj) polyval(obj,x) diff(obj) plot(obj)
Purpose Calculates polynomial roots Evaluates polynomial at specified points Finds difference and approximate derivative Creates a plot of the polynomial function
16-17
16
Plotting the two DocPolynom objects x and p calls most of these methods:
x = DocPolynom([1 0]);
16-18
16-19
16
16-20
17
Designing Related Classes
Example A Simple Class Hierarchy on page 17-2 Example Containing Assets in a Portfolio on page 17-19
17
17-2
The following diagram shows the properties defined for the classes of assets.
DocStocks (is a DocAsset) Inherited Props Description Date Type CurrentValue DocStocks Props NumShares SharePrice
DocBonds (is a DocAsset) Inherited Props Description Date Type CurrentValue DocBonds Props FaceValue Yield CurrentBondYield
DocSavings (is a DocAsset) Inherited Props Description Date Type CurrentValue DocSavings Props InterestRate
The DocStock, DocBond, and DocSavings classes inherit properties from the DocAsset class. In this example, the DocAsset class provides storage for data common to all subclasses and shares methods with these subclasses.
17-3
17
Class
char double char char
Default
'' 0 date 'savings'
Description Description of asset Current value of asset Date when record is created (set by date function) Type of asset (stock, bond, savings)
The following table summarizes the methods for the DocAsset class. DocAsset Class Methods Name
DocAsset disp set.Type
Description Class constructor Displays information about this object Set function for Type. Property tests for correct value when property is set.
17-4
17-5
17
a.Description = description; a.Date = date; a.Type = type; a.CurrentValue = current_value; end end % DocAsset
The MATLAB runtime calls this function whenever an attempt is made to set the Type property, even from within the class constructor function or by assigning an initial value. Therefore, the following statement in the class definition would produce an error:
properties Type = 'cash'; end
The only exception is the set.Type function itself, where the statement:
obj.Type = type;
17-6
simply formats the data for display in a way that is consistent with the formatting of the childs disp method:
function disp(a) % Display a DocAsset object fprintf('Description: %s\nDate: %s\nType: %s\nCurrentValue:%9.2f\n',... a.Description,a.Date,a.Type,a.CurrentValue); end % disp
The DocAsset subclass display methods can now call this method to display the data stored in the parent class. This approach isolates the subclass disp methods from changes to the DocAsset class.
17-7
17
The following table summarizes the properties defined for the DocStock class. DocStock Class Properties Name
NumShares SharePrice
Class
double double
Default
0 0
Description Number of shares of a particular stock Current value of asset Description of asset Current value of asset Date when record is created (set by date function) Type of asset (stock, bond, savings)
The following table summarizes the methods for the DocStock class. DocStock Class Methods Name
DocStock disp
17-8
creates a DocStock object, XdotcomStock, that contains information about a stock asset in Xdotcom Corp. The asset consists of 200 shares that have a per share value of $23.47.
17-9
17
the MATLAB runtime looks for a method in the @DocStock folder called disp. The disp method for the DocStock class produces this output:
Description: Xdotcom Date: 17-Nov-1998 Type: stock Current Value: $2500.00 Number of shares: 100 Share price: $25.00
The following function is the DocStock disp method. When this function returns from the call to the DocAsset disp method, it uses fprintf to display the Numshares and SharePrice property values on the screen:
function disp(s) disp@DocAsset(s) fprintf('Number of shares: %g\nShare price: %3.2f\n',... s.NumShares,s.SharePrice); end % disp
17-10
To use the class, create a folder named @DocBond and save DocBond.m to this folder . The parent folder of @DocBond must be on the MATLAB path. See the addpath function for more information.
The following table summarize the properties defined for the DocBond class DocBond Class Properties Name
FaceValue SharePrice
Class
double double
Default
0 0
Description Face value of the bond Current value of asset Description of asset Current value of asset Date when record is created (set by date function) Type of asset (stock, bond, savings)
The following table summarizes the methods for the DocStock class.
17-11
17
Description Class constructor Displays information about this object and calls the DocAsset disp method Utility function to calculate the bonds current value
17-12
Bonds interest rate or yield Current interest rate being paid by equivalent bonds (used to calculate the current value of the asset) For example, this statement:
b = DocBond('xyzbond',100,4.3,6.2);
creates a DocBond object, b, that contains information about a bond asset xyzbond with a face value of $100, a yield of 4.3%, and also contains information about the current yield of such bonds (6.2% in this case) that is used to calculate the current value. Note The calculations performed in this example are intended only to illustrate the use of MATLAB classes and do not represent a way to determine the actual value of any monetary investment.
17-13
17
the MATLAB runtime looks for a method in the @DocBond folder called disp. The disp method for the DocBond class produces this output:
Description: xyzbond Date: 17-Nov-1998 Type: bond Current Value: $69.35 Face value of bonds: $100 Yield: 4.30%
17-14
The following function is the DocBond disp method. When this function returns from the call to the DocAsset disp method, it uses fprintf to display the FaceValue, Yield, and CurrentValue property values on the screen:
function disp(b) disp@DocAsset(b) % Call DocAsset disp method fprintf('Face value of bonds: $%g\nYield: %3.2f%%\n',... b.FaceValue,b.Yield); end % disp
17-15
17
Class
double
Default
''
Description Current interest rate paid on the savings account Description of asset Current value of asset Date when record is created (set by date function) The type of asset (stock, bond, savings)
Type
char
''
The following table summarizes the methods for the DocSavings class. DocSavings Class Methods Name
DocSavings disp
Description Class constructor Displays information about this object and calls the DocAsset disp method
17-16
creates a DocSavings object, sv, that contains information about an account in MyBank with a balance of $1000 and an interest rate of 2.9%.
17-17
17
the MATLAB runtime looks for a method in the @DocSavings folder called disp. The disp method for the DocSavings class produces this output:
Description: MyBank Date: 17-Nov-1998 Type: savings Current Value: $1000.00 Interest Rate: 2.90%
The following function is the DocSaving disp method. When this function returns from the call to the DocAsset disp method, it uses fprintf to display the Numshares and SharePrice property values on the screen:
function disp(b) disp@DocAsset(b) % Call DocAsset disp method fprintf('%s%3.2f%%\n','Interest Rate: ',s.InterestRate); end % disp
17-18
17-19
17
Class
char cell double
Default
'' {} 0
Description Name of client owning the portfolio A cell array containing individual asset objects Value of all assets (calculated in the constructor method)
The following table summarizes the methods for the DocPortfolio class. DocBond Class Methods Name
DocPortfolio disp
Description Class constructor Displays information about this object and calls the DocAsset disp method Overloaded version of pie3 function designed to take a single portfolio object as an argument
pie3
17-20
17-21
17
The DocPortfolio pie3 Method on page 17-23 provides a graphical display of the portfolio.
17-22
if nargin > 0 p.Name = name; for k = 1:length(varargin) p.IndAssets{k} = varargin(k); asset_value = p.IndAssets{k}{1}.CurrentValue; p.TotalValue = p.TotalValue + asset_value; end end end % DocPortfolio
17-23
17
end % for % Step 2: Create labels and data for the pie graph k = 1; if stock_amt ~= 0 label(k) = {'Stocks'}; pie_vector(k) = stock_amt; k = k + 1; end % if if bond_amt ~= 0 label(k) = {'Bonds'}; pie_vector(k) = bond_amt; k = k + 1; end % if if savings_amt ~= 0 label(k) = {'Savings'}; pie_vector(k) = savings_amt; end % if % Step 3: Call pie3, adjust fonts and colors pie3(pie_vector,label);set(gcf,'Renderer','zbuffer') set(findobj(gca,'Type','Text'),... 'FontSize',14,'FontWeight','bold') colormap prism stg(1) = {['Portfolio Composition for ',p.Name]}; stg(2) = {['Total Value of Assets: $',num2str(p.TotalValue,'%0.2f')]}; title(stg,'FontSize',10) end % pie3
There are three parts in the overloaded pie3 method. Step 1 Get the CurrentValue property of each contained asset object and determine the total value in each category. Step 2 Create the pie chart labels and build a vector of graph data, depending on which objects are present in the portfolio. Step 3 Call the MATLAB pie3 function, make some font and colormap adjustments, and add a title.
17-24
Visualizing a Portfolio
You can use a DocPortfolio object to present an individuals financial portfolio. For example, given the following assets:
XYZStock = DocStock('XYZ Stocks',200,12.34); USTBonds = DocBond('U.S. Treasury Bonds',1600,3.2,2.8); SaveAccount = DocSavings('MyBank Acc # 123',2000,6); VictoriaSelna = DocPortfolio('Victoria Selna',... XYZStock,... SaveAccount,... USTBonds);
you can use the classs pie3 method to display the relative mix of assets as a pie chart.
pie3(VictoriaSelna)
17-25
17
17-26
Index
A
Index
C
classes defining 3-5 value classes 5-4
overloading subscripting 15-18 objects as indices into objects 15-32 overloaded function 7-26 overloading 15-18 arithmetic operators 16-14 functions 16-16 pie3 17-23
E
end method 15-31
P
pie3 function overloaded 17-23
F
functions overloading 16-16
R
reference, subscripted 15-18
S
subscripted assignment 15-23 subscripting overloading 15-18 subsref 15-18
M
methods
end 15-31
O
object-oriented programming
V
value classes 5-4
Index-1