1. Trang chủ
  2. » Kỹ Thuật - Công Nghệ

CRC.Press A Guide to MATLAB Object Oriented Programming May.2007 Episode 1 Part 9 ppsx

20 369 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 20
Dung lượng 801,38 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

They can be assigned into structure elements and even used as a private member variable for another class.. 140 A Guide to MATLAB Object-Oriented ProgrammingNow in its third version, Cla

Trang 1

134 A Guide to MATLAB Object-Oriented Programming

shape = cShape;

shape = draw(shape);

draws the figure shown in Figure 10.1 When the size and scale factors change, pay close attention

to the axes We are allowing MATLAB to scale the plot automatically We could improve on that situation by designing in another set of scale-related member variables and functions For this test drive, automatic scaling is okay

Change the color to red using either

shape.ColorRgb = [1; 0; 0];

or

shape = set(shape, ‘ColorRgb’, [1; 0; 0]);

Clients should usually use dot-reference syntax vs set, but the result from either is the same The object will automatically redraw itself, and the new red star is shown in Figure 10.2

FIGURE 10.1 Default graphic for cShape object.

FIGURE 10.2 cShape graphic after assigning an RGB color of [1; 0; 0].

Trang 2

Drawing a Shape 135

The size can be changed in two ways, via the public member variable Size or by multiplying

by a scaling constant Changing the Size with

shape.Size = [2; 3];

results in the plot shown in Figure 10.3 The star takes up the same position in the plot; however, notice that the scales have changed

The figure’s size can also be changed by multiplying the shape by a constant For example, the command

shape = 0.25 * shape;

results in the plot shown in Figure 10.4 Again, note the change in the scale Multiplying is not quite the same as assigning the Size variable because multiplication also sets the private variable

mScale The only real implication of the difference occurs during reset

FIGURE 10.3 cShape graphic scaled using the size mutator.

FIGURE 10.4 cShape graphic scaled using the overloaded mtimes.

Trang 3

136 A Guide to MATLAB Object-Oriented Programming

The reset command

shape = reset(shape);

closes the figure window and resets private member variables back to undrawn values

Arrays of cShape objects can also be drawn For example, the set of commands

clear all;

shape = [cShape cShape];

shape(2).ColorRgb = [0; 1; 0];

shape(2).Points = [[-1; -1] [-1; 1] [1; 1] [1; -1] [-1; -1]]; shape(2) = [0.75; 0.25] * shape(2);

shape = draw(shape);

results in the figure shown in Figure 10.5 The commands build a length-2 array of cShape objects, and set the shape at index 2 so that it is first a green square The x-direction is scaled by three fourths, and the y-direction is scaled by one fourth Finally, when the shape array is drawn, both the default blue star and the mutated green rectangle are drawn in the same figure

10.3 SUMMARY

This concludes the section on encapsulation We have now uncovered most of the major issues involved in MATLAB object-oriented programming The functions developed to support encapsu-lation can easily serve as a reference design for classes without inheritance Group-of-eight functions should be included in every class you write To do otherwise compromises encapsulation in some way The group of eight functions are as follows:

• constructor

FIGURE 10.5 Graphic for an array of cShape objects.

Trang 4

Drawing a Shape 137

Four in this group can be reused with no class-dependent tailoring It is possible to isolate these four into their own directory; however, it involves more complexity than it is worth It is much easier to copy them into each new class directory The remaining four — constructor, get, set, and fieldnames —are organized to make class-dependent tailoring as easy as possible The organization includes private variables, public variables, and so-called concealed variables Fortu-nately, some of the most difficult code in the class-dependent functions is not class dependent Member names and the specific case code used to manage the conversion from public to private data are class dependent, but functionality like tab completion and multilevel indexing is identical from class to class

Including all members in the group of eight gives our objects first-class status among MAT-LAB’s built-in types Object variables can be passed as arguments Object variables can also be saved and loaded They can be assigned into structure elements and even used as a private member variable for another class Objects can be displayed, turned into structures, and, with additional member functions, converted into other types In short, attention to detail makes objects appear as

if they are an intrinsic part of the language Indeed, that is exactly how it should be

In the remaining sections, we will reexamine constructors, examine inheritance, and discuss many “gee-whiz” ideas These topics are important but not nearly as important as encapsulation and the group of eight As we will see, the organization included in the group of eight makes inheritance much easier to implement Several standard functions will be added to the class, but these pale in importance next to the group of eight

10.4 INDEPENDENT INVESTIGATIONS

1 Add member variables and functions that would allow clients to set the scale

2 Like color, allow clients to specify the line style

3 Instead of setting corner points, allow a client to pass in strings like ‘Square’ and

‘Triangle’ Can you do this by modifying the code found in case ‘Points’

inside set? Do you need a string like ‘Rectangle’? Think about the public variable

Size

4 Add member variables and functions that allow clients to rotate the shape

Trang 6

Part 2

Building a Hierarchy

This section focuses on building hierarchies because objects and hierarchies go hand in hand For example, a hierarchy of shapes might include rectangles, stars, and circles A hierarchical imple-mentation allows one class to build on functions defined in another class An object-oriented hierarchy can do this without a lot of rework Throughout the first section, we simplified much of our code by coercing MATLAB into doing a lot of the work In a small way, all classes are hierarchical because they build on the built-in types MATLAB is always at the top of the hierarchy

A deeper hierarchy of classes follows the same philosophy The lower-level class, sometimes called the child, tries to coerce a higher-level class, the parent, into doing as much as possible This is the way of a hierarchy: always try to force the next higher level into doing all the work

When a child class coerces a parent to perform an operation, the child is said to inherit that particular function from the parent There are different flavors of inheritance Differences depend

on how control passes to the parent A parent–child relationship is what we normally think of as inheritance, but anytime one class passes control to another, this is inheritance When one class uses another class as a private member variable, this too is inheritance Called composition or aggrega-tion, using a class as a member variable often works better than parent–child inheritance and is just as powerful In this section, we will examine both parent–child inheritance and composition Also in this section, we will find that efficient, bulletproof hierarchies can be coded in MATLAB Hierarchies are built using both types of inheritance, parent–child and composition The group-of-eight implementations from Section 1 are already organized to support inheritance In this section,

we will expand on the organization

Recall from the first section how we tailored built-in MATLAB functions like subsref,

subsasgn, display, and even mtimes to suit the needs of our classes In a hierarchy, a child class can accomplish the same trick This time, the child tailors a function already defined by the parent The child simply includes a tailored version of the function in its own class directory In the first section, even when a class redefined a function, we could still call MATLAB’s built-in version using builtin When a child redefines a parent function, a similar mechanism allows a child to call the parent’s version We can’t use builtin because that will skip over the parent

By the end of this section, you will be able to churn out bulletproof class implementations based on the reference designs Soon the novelty will wear off and you will pine for a computer-aided way to create the group-of-eight scaffolding The CD that accompanies this book includes a very complete MATLAB tool that will build the scaffolding and help you maintain and evolve each class The last two chapters in this section document and demonstrate the Class Wizard tool

C911X_S002.fm Page 139 Thursday, March 1, 2007 2:38 PM

Trang 7

140 A Guide to MATLAB Object-Oriented Programming

Now in its third version, Class Wizard will rapidly generate core class functions based on lists

of private and public variables and functions These lists are entered using a graphical interface Once entered, Class Wizard generates group-of-eight functions that include all the special func-tionality discussed throughout this book Class Wizard is a versatile and extremely powerful tool

It is found on the disk in /utils/wizard_gui, and this directory must be added to the path The dialog screens in Class Wizard require MATLAB version 7 or greater but will generate classes that work with version 6.5 or greater

C911X_S002.fm Page 140 Thursday, March 1, 2007 2:38 PM

Trang 8

11 Constructor Redux

In the first part of this book, objects were constructed in the most basic way because no arguments were passed into the constructor With a no-argument constructor, all objects are constructed using the same initial values For the Part 1 cShape class, this basic approach worked because Part 1 focused primarily on encapsulation mechanics Now that we understand encapsulation, we will turn our attention to inheritance and the development of class hierarchies With the development

of class hierarchies, we also need a richer set of construction options

For example, if we want cShape to serve as a parent for cStar and cSquare, the construc-tors for cStar and cSquare need to initialize mPoints with different values The best time to perform the initialization is during construction, and a constructor that accepts arguments is the best way to tailor the construction process Instead of relying on hard-coded values, constructor arguments are used to initialize private variables As with any function, we can pass any number

of arguments into the constructor through varargin The number of arguments along with their types can then be used to select the appropriate initialization commands Different classes have different construction requirements In this chapter, we develop an extendable organization we can use to implement general-purpose constructors

11.1 SPECIFYING INITIAL VALUES

Two initial-value cases are so common that they have special names The no-argument constructor

is called the default constructor We already know much about the default constructor because the default constructor was the constructor used in Part 1 For example, we know that MATLAB requires

a default constructor for every class The other common constructor is called the copy constructor The copy constructor is a one-argument constructor and the lone argument has the same type as the name of the constructor The copy constructor makes a copy of an existing object; however, in MATLAB, assignment also makes a copy Assignment syntax is much easier and that diminishes the importance of a copy constructor Perhaps the only difference between the two is the fact that

we can tailor the copy constructor but we can’t tailor assignment The copy constructor is still important enough to be included in the standard implementation

The standard object-oriented vocabulary gives these constructors different names because most object-oriented languages implement each constructor using a different function Other languages can do this because their compiler or interpreter uses the number of arguments and the type of each to select an appropriate function MATLAB works differently In MATLAB, every class has only one constructor To get multiple-constructor functionality, code inside the constructor steers the execution based on the value of nargin Code for each nargin value can further inspect an argument’s type and take appropriate action

In addition to a default constructor and a copy constructor, a class can define constructors with any number of input arguments of any type.* Different classes have different construction needs, and that means every class’ constructor is unique in terms of number of inputs and input types The challenge in this chapter is to generalize all of these unique requirements into an implementation strategy that can be universally applied

* The standard terminology is a little sloppy when we consider that MATLAB has only one constructor When I talk about

a specific type of constructor (e.g., copy or default), what I really mean is one of the unique execution paths through the constructor function Each unique execution path is selected based on the number of input arguments and their types C911X_C011.fm Page 141 Thursday, March 1, 2007 2:42 PM

Trang 9

142 A Guide to MATLAB Object-Oriented Programming

We already know how to construct a default object In fact, our current default constructor optimizes run time by saving a copy of the default object as a persistent variable Thus, it seems reasonable to begin the general construction process by first constructing a default object Beginning with a default object is more than reasonable: it is essential for the development of a robust, maintainable set of constructors For a particular type, MATLAB saves the object’s structure during the very first call to class Later, if the constructor calls class with a different structure, MATLAB throws an error Beginning with a default object will eliminate structure-mismatch errors that might otherwise occur between different constructors

Once we have a default object, a switch based on the value in nargin seems to be the best choice; however, a switch statement does not support a general-purpose implementation A switch

is not general because both the number of cases and the nargin value for each case change from class to class A more general but much less obvious approach breaks out code associated with each supported nargin value into a separate m-file Following a standard naming convention for each of these m-files allows the constructor to build the name on the fly and use feval to call it Following the more general feval approach is consistent with the group-of-eight design goal

of building a robust implementation that will withstand the test of time The constructor is robust because the same underlying code is always used The constructor also tolerates change because private variables and nargin conditions can be added without upsetting functions that already exist Using feval in this way can sometimes result in poor run-time performance In those situations, the constructor can be tailored to use a switch-case approach Individual cases can still call a separate m-file because the run-time improvement comes from eliminating the feval

overhead

At first, it seems that giving every supported nargin value its own function would add too many files to each class directory Fortunately, function-search rules give us a way out of this dilemma The so-called helper functions can be located in the class’ private directory As private member functions, they are not included in the public interface yet they are still available to the constructor Private functions represent an important topic and before we get too involved with inheritance, we will take another brief side trip to examine the private class directory

11.1.1 P RIVATE M EMBER F UNCTIONS

In the previous discussion of path-search priority, §3.2.3, the class directory was listed as third in priority Both subfunctions and the private directory have higher priority This priority system means that functions located in a class’ private directory are callable from only two locations: the class directory and the private directory itself The fact that the private directory is included represents

a minor deviation from standard function-search rules It means that functions in one private directory cannot call functions located in another private directory For example, functions located

in /@cShape/private cannot call a function located in /@cShape/private/private

In this way, both public and private member functions can call all other member functions, both public and private

Functions located in a class’ private directory are not part of the public interface because a client can’t call them Just like private member variables, the only functions able to access private member functions are other member functions An m-file in the class directory is a public member function, and an m-file in the class’ private directory is a private member function It really is that easy

The use of /private gives us an opportunity to modularize class functions and improve maintainability Just like public member functions, a private member function can read and write private member variables and call other member functions For the constructor, each nargin -specific function can be located in a class’ private directory This move helps simplify the constructor

to the point where it can be made almost entirely class independent Other functions in the group

of eight can also benefit from private functions For example, complicated get and set cases

C911X_C011.fm Page 142 Thursday, March 1, 2007 2:42 PM

Trang 10

Constructor Redux 143

can be isolated in a private member function Being second in priority also means that MATLAB

can find private functions even if they do not use an object as an input argument This makes the

private directory a very convenient location for class-specific utility functions and encourages the

development of modular code

Under some conditions, a private member function can also improve run time For example, a

private function might allow member functions to get and set public variables without having to

go through the overhead involved in get and set This sets up more coupling than we usually

prefer Sometimes the run-time improvement is worth the trade Member functions outside the

group of eight can also use private member functions to share common code, increase modularity,

and sometimes improve performance

11.2 GENERALIZING THE CONSTRUCTOR

We can use a standard file-naming convention and private member functions to generalize the

constructor Except for calls to superiorto and inferiorto, the constructor file itself is class

independent The class-dependent sections from the previous version of the constructor can be

found in the class’ private directory All the code used to build and initialize the default structure

can be found in the private member function named ctor_ini.m The abbreviation ctor is

short for constructor, and the abbreviation ini is short for initialization Code to convert the

structure into an object, code to modify the superiority, and code to save the persistent copy will

still be found in the main constructor function

The nargin-dependent functions can also be found in the class’ private directory The function

used for one input argument is named ctor_1.m; for two input arguments, ctor_2.m; and so

on for any number of input arguments There is no “numbered-ctor” function for the no-argument

constructor because ctor_ini in conjunction with the main constructor function already produces

a default object We also don’t include a numbered-ctor function for nargin conditions that we

don’t intend to support This allows the main constructor to detect undefined-function errors and

throw a different error with a more appropriate error message Supporting a new nargin value

simply means developing another numbered-ctor function and adding it to the private directory

Similarly, deleting a numbered-ctor function will remove support for the associated nargin

value This flexibility can be used to support development, testing, and quality assurance through

construction methods not available to general clients

The main constructor function is shown in Code Listing 60 and can be analyzed in two sections

The first section, lines 2–15, is the default, no-argument constructor; and the second section, lines

17–30, overwrites default values using any number of input arguments As you examine the listing,

note the complete absence of class-specific commands Class-specific information is obtained in

line 6 by calling ctor_ini

Code Listing 60, Improved Constructor without Inheritance

'cShape'

3

ctor_ini.m

C911X_C011.fm Page 143 Thursday, March 1, 2007 2:42 PM

Ngày đăng: 05/08/2014, 21:21