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

CRC.Press A Guide to MATLAB Object Oriented Programming May.2007 Episode 2 Part 6 docx

20 232 0
Tài liệu đã được kiểm tra trùng lặp

Đ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 542,69 KB

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

Nội dung

A general container is different from an array because it can hold different types.. A general container is different from a cell array because all objects must descend from the same par

Trang 1

274 A Guide to MATLAB Object-Oriented Programming

18 >> star.Size = [2;3];

19 >> disp(star.Size')

21 >> star

22 star =

26 LineWeight: 'normal'

28 >> fieldnames(star)

29 ans =

31 'ColorRgb'

33 'LineWeight'

35 >> fieldnames(star, '-full')

36 ans =

37 ans =

38 'Size % double array (2x1)'

39 'ColorRgb % double array (3x1)'

40 'Points % double array (2xN)'

41 'LineWeight % normal, bold'

42 'Title % string'

43 >> fieldnames(star, '-possible')

44 ans =

46 {1x1 cell}

47 'ColorRgb'

48 {1x1 cell}

50 {1x1 cell}

51 'LineWeight'

52 {1x1 cell}

54 {1x1 cell}

55 >> struct(star)

59 LineWeight: 'normal'

61 >> star = [cStar cStar; cStar cStar];

62 >> size(star)

63 ans =

Trang 2

Class Wizard Versions of the Shape Hierarchy 275

Attending to the myriad details is something that a CASE tool can do very well Even this is difficult unless there is a good organizational structure The organizational structure advocated by the preceding chapters results in good class implementation, and Class Wizard is very helpful in maintaining that structure This is particularly true when the class definition evolves With Class Wizard, evolution is a simple matter of adding elements to the definition and rebuilding the files Files managed by the tool are overwritten with the new definition, while handcrafted files are untouched The best balance is always maintained between standard idioms and a developer’s creativity

18.7 INDEPENDENT INVESTIGATIONS

1 Repeat the test-drive commands using cDiamond objects instead of cShape objects

2 Modify the class interfaces to allow shapes to be rotated by an arbitrary angle Use Class Wizard to generate the initial versions of helper functions and public member functions

3 Add other line-style features to cLineStyle, and expose these features so that clients can use them with cStar and cDiamond objects (for example, dotted vs solid lines)

4 Add a cCircle class to the hierarchy Does cCircle inherit cShape or is there a better relationship? Should /@cCircle/draw use polar instead of plot? How would the use of polar change the organization?

65 >> [star.Size]

66 ans =

67 1 1 1 1

68 1 1 1 1

69 >> {star.Size}

70 ans =

71 [2x1 double] [2x1 double] [2x1 double] [2x1 double]

72 >>

73 >> disp(class(star))

74 cStar

75 >> disp(isa(star, 'cShape'))

77 >> disp(isa(star, 'cDiamond'))

Trang 4

Part 3

Advanced Strategies

In this section, we redeploy standard object-oriented techniques in a way that allows MATLAB to create a few special-purpose classes commonly found in other object-oriented languages These include containers, singleton objects, functors, and iterators These classes require strong encap-sulation and a flexible object-oriented language The fact that these sophisticated classes can be created from elements that already exist pays tribute to the MATLAB design team If these example classes make you wonder what else is possible, they have done their job With a little imagination and creativity, anything is possible

Some of the topics in this section are controversial because they upset the status quo Redefining member-function syntax, adding a pass-by-reference function model, and obtaining protected vis-ibility for variables and functions are probably the most disruptive topics The discussions don’t try to judge whether you should adopt a particular technique, but instead try to demonstrate the flexibility inherent in MATLAB objects and expand the way you think about them Some of the techniques are worthy of adoption, while others would benefit from more support from the language and the user community Like many disruptive technologies, it is hard to know in advance what will be embraced Unlike many languages, MATLAB’s evolution isn’t restricted by an ISO standard

If enough of us adopt a few of these techniques, market forces will ultimately prevail

C911X_S003.fm Page 277 Friday, March 2, 2007 9:09 AM

Trang 5

C911X_S003.fm Page 278 Friday, March 2, 2007 9:09 AM

Trang 6

Container Class

As a further demonstration of composition, we make an initial foray into designing and imple-menting a general container class A general container is different from an array because it can hold different types A general container is different from a cell array because all objects must descend from the same parent For example, a general cShape container can hold both cStar

and cDiamond objects because they both use cShape as a parent A container is also different from a cell array because a container has a structure-like interface The interface makes a container behave a lot like an object array Rather than looping over each element in the container, clients can use vector syntax Often the loop still exists; however, it is now hidden behind the container’s interface

Developing a set of standard containers compatible with the general computer-engineering literature* or with National Institute of Standards (NIST) definitions** would be an enormous undertaking The goals for this chapter’s container are much less ambitious The primary goal is

to demonstrate one potential use of composition A secondary goal is to produce a container that might be useful as is, or at least produce a container that can be easily improved The container developed for this chapter isn’t perfect, but with what you already know, you can fix all of its deficiencies

19.1 BUILDING CONTAINERS

To implement a container, several details are important First, we need to specify the object type held by the container Any object that passes an isa test for the specified type will be allowed in Thus, objects of the specified type and objects using the specified type as a parent are okay to add

to the container For the example, we will specify cShape as the object type That will allow the container to hold cShape, cStar, and cDiamond objects If we want to create new shape classes, the container will hold them too Of course, these new classes must have cShape somewhere in their hierarchy so that isa(object, ‘cShape’) returns true

The next thing we need to decide is how the container implementation will store the objects MATLAB will not let us use a built-in type, like cell, as a parent, so we must look for an alternative There are two options but both represent compromises The first and probably the most obvious approach stores objects in a private cell array Cell array storage is probably the best approach because it aligns public and private indices One potential problem with this approach is the mismatch among built-in functions like length and size and the number of objects held in the container Of course, we will code around this problem by overloading length and size

We might also want to consider overloading reshape, ndims, numel, num2cell, and

mat2cell, among others

The next potential problem with a private cell array is the index value end Using end to add

a new element to the container should work the same as adding an element to an array For example, the command syntax might look like the following:

* Cardelli, L., and Wegner, P “On Understanding Types, Data Abstraction and Polymorphism,” ACM Computer Survey,

17, 4, December 1985, 471–522.

** http://www.nist.gov/dads/.

C911X_C019.fm Page 279 Friday, March 2, 2007 9:42 AM

Trang 7

280 A Guide to MATLAB Object-Oriented Programming

shape_array(end+1) = cStar;

The built-in behavior of end returns the dimension of shape_array, not the dimension of the

private cell array inside shape_array Redefining size and length doesn’t help, but thanks

to the foresight of the MATLAB developers, we can code around this problem too In this situation,

end acts like an operator Like any operator, MATLAB converts end into a function call This

behavior allows us to overload the function end.m to return an appropriate value

An alternate container solution avoids length, size, reshape, and end issues by taking

advantage of the way MATLAB implements structures For example, the container class might

include a private member variable named m O b j e c t After several additions,

class(this(1).mObject) might equal ‘cStar’ and class(this(2).mObject)

might equal ‘cDiamond’ MATLAB allows different object types stored in the mObject element

to coexist As long as we never try to concatenate mObject elements (i.e., [this.mObject]),

everything will work fine With this solution, adding a new object simply increases the size of the

private structure The primary problem with this approach involves repeating the container’s private

structure and the fact that arrays of structures are memory hogs Using repmat can also produce

inconsistent results

Regardless of the approach, we also need to consider concatenation with cat, horzcat, and

vertcat Achieving the best compatibility means supporting the concatenation of a container

and an object and the concatenation of two or more containers We usually don’t want to restrict

the concatenation order, and that means the container must be superiorto the classes it holds

19.2 CONTAINER IMPLEMENTATION

For implementation purposes, this chapter uses the cell-array approach With the cell-array

approach, the container object itself is never empty even when the private cell array contains no

objects This eliminates the potential for empty-object memory errors that sometimes arise.* The

cell-array approach requires a little more work up front, but the result seems to be more robust

compared to the object-array approach After the first container implementation, the added workload

isn’t a problem because most of the tailored functions can be copied, as is, to other container

implementations

The implementation example is organized into three sections The first section focuses on our

standard group-of-eight framework The second section focuses on a set of tailored functions that

overload the behavior of standard MATLAB built-in functions The third section focuses on

cShape-specific functions The implementation of any container can be organized along these

divisions

19.2.1 T HE S TANDARD F RAMEWORK AND THE G ROUP OF E IGHT

Even though a container class is quite different from the other class examples, we don’t have to

code everything from scratch Instead, use Class Wizard to generate the initial set of files and

modify them to suit the needs of the container The constructor, ctor_ini, ctor_1, display,

parent_list, and struct won’t need modifications The remaining group-of-eight functions

fieldnames, get, set, subsref, and subsasgn — will need container-specific changes

The changes are modest and are relatively easy since the generated code serves as a guide The

data entered into Class Wizard are provided in Table 19.1 through Table 19.4 The list of function

names in Table 19.3 provides a preview of the tailoring to come Fields not listed in the tables

should remain set to their default values The complete Class Wizard mat file and the unmodified

* Versions 7.1 and earlier are not stable when repmat is used to create an object array with a dimension size equal to

zero Returning a so-called empty object from a constructor is particularly bad The fact that a default-constructed container

should be empty makes the repeated-structure approach unreliable in these versions.

C911X_C019.fm Page 280 Friday, March 2, 2007 9:42 AM

Trang 8

Composition and a Simple Container Class 281

results are included in /chapter_0/as_generated cShapeArray After entering the data, generate the class

The container itself contains no public member variables, and, as generated by Class Wizard, the public variable sections inside fieldnames, get, and set are empty These sections will not remain empty Instead, these functions will forward public variable requests to the secondary objects stored in the container The Class Wizard cases inside subsref and subsasgn also need some changes The initial code assumes the container itself is an array In reality, the container class is always scalar Changes to subsref and subsasgn use the private cell array to make the container look like an array The dot-reference case is okay because changes to get and set

determine dot-reference behavior The array-reference case needs to access and mutate objects held in the container’s cell array Only the highlights are included in the following sections The fully modified files are included in /chapter_0/@cShapeArray

19.2.1.1 Container Modifications to fieldnames

Since the container itself has no public variables, fieldnames.m doesn’t initially contain a list

of public names This is correct because only the objects held by the container have public variables The container needs to return a list of public names, but it doesn’t need an explicit list Rather than coding an explicit name list inside the container’s version of fieldnames, we simply forward the fieldnames request and collect the result There are two potential targets for the forward: the class type held in this.mType (see Table 19.2) and the objects held in this.mArray (see Table 19.2) Choosing the first returns the public members allocated to the parent These names are guaranteed to exist for every object in the container Choosing the latter also includes parent-class public names, but it might also include public names defined for the children Choosing the latter also means that any particular object may or may not contain every public variable listed This is not necessarily a problem, but it is something that must be considered when container functions are implemented

For cShape and its children, most of the public variables are defined by the parent In this situation, using the container class type held in this.mType is a good choice This choice also

TABLE 19.1 cShapeArray Class Wizard Main Dialog Fields

Class Name cShapeArray Superior To cShape, cStar, cDiamond, double

TABLE 19.2

cShapeArray Private Variable Dialog Fields

passes isa(object, this.mType).

mFigHandle [] Figure handle where all contained shapes

are drawn.

Trang 9

282 A Guide to MATLAB Object-Oriented Programming

TABLE 19.3

cShapeArray Public Function Field Values

Function

Name

Input Argument List

Output

FigureHandle

in the container If FigureHandle is not passed

in, draw will manage the use

or creation of a figure window.

Returns an index value consistent with “end.” If n

is not equal to length(size(this.mObject)), some reshaping is done to find the correct value.

Returns the correct length based on the number of objects in the container.

Function is not supported; throws an error if called.

for * Allows multiplication between the container and arrays of doubles.

for * Allows multiplication between the container and arrays of doubles.

Returns the correct ndims value based on the shape of the container’s mObject cell array.

Trang 10

Composition and a Simple Container Class 283

allows the container to return a list of names even when the container is empty Add the following command to the end of the initial version of @cShapeArray/fieldnames.m

names = [names; fieldnames(feval(this.mType), varargin{:})];

In this command, feval(this.mType) creates a temporary object and varargin{:}

expands input arguments The complete list of names is created by concatenating the return value with any names that already exist To improve run time, the result could be assigned to a persistent variable Use the profiler to determine when a persistent is warranted

19.2.1.2 Container Modifications to subsref

For dot-reference operations, the container needs to forward the operation to the objects held in the container The best location for the forward isn’t in subsref but rather in get Locating the forward inside get means no changes to subsref’s dot-reference case

For array-reference operations, the input index value is used to return elements in the container’s cell array In the normal situation, the built-in version of subsref and MATLAB’s assignment operator cooperate to return a subset array with the same type as this The container’s array-reference code can’t rely on the same built-in behavior Instead, the code first constructs an empty container and then assigns the indexed subset into the new container’s mArray variable Modifications to subsref’s array-reference case are shown in Code Listing 109

Line 2 instantiates a new container object by calling the constructor Class(this) returns the name of the constructor and feval executes it No arguments are passed with the function call so the result is an empty container Line 3 uses index(1) to get the correct subset out of

TABLE 19.3 (CONTINUED)

cShapeArray Public Function Field Values

Function

Name

Input Argument List

Output

num2cell this, varargin container_

cells

Redefines built-in behavior Use this function to access the container’s entire cell array Function only supports one input argument If you try to pass in a direction, the function will throw an error.

in the container.

size this, varargin varargout Redefines built-in behavior

Returns the correct size array based on the number of objects in the container Reshape this, varargin this Redefines built-in behavior

Reshapes the object cell array.

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