Vous êtes sur la page 1sur 144

Modularity and Object-Oriented Programming OO

Steven Zeil November 13, 2001

1. OOP Philosphy 2. OOP Languages 3. Working With Inheritance 4. Some OOP Languages 5. Implementing OO

1. OOP Philosphy
OOP stems from work in Simula, a simulation language. Every program is a model of some part of the world. The quality of a program design is directly proportional to how faithfully it reects the structure of the world that it models.

What is an Object? An object is characterized by 1. Identity 2. State 3. Behavior

1.1. Identity
Identity is the property of an object that distinguishes it from all others. names: Steve, George, x, y references: this, that, P, p

1.2. State
The state of an object consists of the properties of the object, and the current values of those properties. Consider a book:
s t r u c t Book { string t i t l e ; Author a u t h o r ; ISBN i s b n ; int edition ; 6

i n t year ; Publisher publisher ; };

Does this have state?

No, it names properties but has no values. Here, however, is a book object:
Book cs355Text = { Programming Languages , sethi , 0201590654 , 2, 1996, addisonWesley } ;

1.3. Behavior
Behavior is how an object acts and reacts to operations on it, in terms of visible state changes and operations on other visible objects. In OOP, behavior is often described in terms of messages and methods. A message to an object is a request for service.
9

A method is the internal means by which the object responds.

10

Different objects may respond to the same message via different methods. Example: I send a message send owers to my grandmother to

11

Different objects may respond to the same message via different methods. Example: I send a message send owers to my grandmother to a orist

11

Different objects may respond to the same message via different methods. Example: I send a message send owers to my grandmother to a orist my wife

11

Different objects may respond to the same message via different methods. Example: I send a message send owers to my grandmother to a orist my wife a secretary

11

Different objects may respond to the same message via different methods. Example: I send a message send owers to my grandmother to a orist my wife a secretary a tree
11

In using objects, we must know what messages they will successfully respond to, not necessarily the method of the response.

12

1.4. Are objects new?


In some ways, these are familiar programming concepts already:
OOPL object identity state class message method passing a message traditional PL variable , constant label, name, address value type funct decl funct body funct call 13

2. OOP Languages
Essential characteristics of OOPLs: 1. Inheritance 2. Subtyping 3. Dynamic Binding

14

2.1. Inheritance
A class C inherits from class D if C has all the data members and messages of D. C may have additional data members and messages not present in D. D is called a base class of C.

15

Ada has a very pure form of inheritance. Given


package Ovens i s type Oven i s p r i v a t e ; function temp ( o : Oven ) r e t u r n s r e a l ; procedure setTemp ( o : i n out Oven , desired : real ) ; private type Oven i s record setting : real ; temp : r e a l ; 16

end record ; end Ovens ;

17

We can then write


with Ovens ; use Ovens ; package MoreOvens i s type MicrowaveOven i s new Oven ; procedure s e t T i m e r ( o : i n out Oven , desired : real ) ; end MoreOvens ;

MicrowaveOven inherits the data and functions of Oven. It adds a new procedure, setTimer.
18

procedure bakeBread ( o : i n o u t Oven ) ; o : Oven ; m: MicrowaveOven ; setTemp ( o , v ) ; OK setTemp (m, v ) ; OK ( i n h ) setTimer ( o , t ); i l l e g a l s e t T i m e r (m, t ) ; OK bakeBread ( o ) ; OK bakeBread (m) ; i l l e g a l

19

2.2. Subtyping
A type C is a subtype of D if a value of type C may be used in any operation that expects a value of type D. C is called a subclass or subtype of D. D is called a superclass or supertype of C.

20

As a general rule, OOPLs combine inheritance and subtyping.


class Oven { public : double temp ( ) const ; void setTemp ( d e s i r e d : r e a l ) ; private : double s e t t i n g ; double t e mp e r a t u r e ; };

21

C++/Java combine inheritance and subtyping.


class MicrowaveOven : public Oven { public : void s e t T i m e r ( double ) ; private : double t i m e ; };

22

void bakeBread ( const Oven & ) ; Oven o ; MicrowaveOven m; o . setTemp ( v ) ; OK m. setTemp ( v ) ; OK ( i n h ) o . setTimer ( t ); i l l e g a l m. s e t T i m e r ( t ) ; OK bakeBread ( o ) ; OK bakeBread (m) ; OK ( sub ) 23

2.2.1. Subtyping: Linked List As an example of subtyping in action, consider a doubly linked list. It is convenient for many reasons to organize the list as a pair of rings, linked at the beginning and end via a header node.

24

Adams Baker

Cook

25

We might rst try:


struct Node { string data; Node *prev; Node* next; }; struct Header { int listSize; Node* last; Node* first; };

But sometimes a Node must point to a Header rather than another Node.

26

An elegant solution is offered by subtyping. Suppose that Node and Header were each subtypes of another type, DLLBase. Then by the subtyping rule, a Node or Header could be substituted anywhere a DLLBase was expected

27

s t r u c t DLLBase { } ; s t r u c t Node : public DLLBase { s t r i n g data ; DLLBase prev ; DLLBase n e x t ; }; s t r u c t Header : public DLLBase { int listSize ; DLLBase l a s t ; 28

DLLBase f i r s t ; };

29

Still not ideal, because code like


DLLBase p = header> f i r s t ; while ( p ! = header ) { process ( p>data ) ; p = p>n e x t ; }

fails because a DLLBase does not have next or data elds.

30

We can rewrite using casts:


DLLBase p = header> f i r s t ; while ( p ! = header ) { process ( ( ( Node ) p)>data ) ; p = ( ( Node ) p)>n e x t ; }

31

or we can recognize that everything in this list has two pointers.


L 3

Adams Baker

Cook

32

s t r u c t DLLBase { DLLBase backward ; DLLBase f o r w a r d ; };

s t r u c t Node : public DLLBase { s t r i n g data ; };

33

s t r u c t Header : public DLLBase { int listSize ; };

34

DLLBase p = header>f o r w a r d ; while ( p ! = header ) { process ( ( ( Node ) p)>data ) ; p = p>f o r w a r d ; }

Although we still have a type cast, this is relatively insignicant.

35

If I package up my DLList as an ADT, I will have something like:

36

class StringList { private: Header* header; public: typedef DLLBase* Position; StringList(); StringList(); Position begin() const {return header->next();} Position end() const {return header;} Position next(Position p) const {return p->next;} Position prev(Position p) const {return p->prev;} /* ... insert, erase, find ... */ string& at(Position p) {return ((Node*)p)->data;} };

37

38

2.3. Dynamic Binding


Consider the binding of function body (method) to a function call. Given the following:
a = foo ( b ) ;

when is the decision made as to what code will be executed for this call to foo?

39

2.3.1. Static Binding


a = foo ( b ) ;

In a traditional, compiled imperative language (FORTRAN, PASCAL, C, etc.), the decision is made at compile-time. Decision is immutable If this statement is inside a loop, same code will be invoked for foo each time. Compile-time binding low execution-time
40

overhead.

41

2.3.2. Unconstrained Dynamic Binding


a = foo ( b ) ;

In a traditionally interpreted language (LISP, BASIC, etc), the decision is made at run-time. Decision is often mutable If this statement is inside a loop, different code may be invoked for foo each time. Run-time binding high execution-time overhead.
42

2.3.3. OOP Dynamic Binding OOPLs typically feature an intermediate form of dynamic binding in which the choice of method is made from a relatively small list of options.

43

OO Dynamic Binding list is determined at compile time

44

OO Dynamic Binding list is determined at compile time nal choice made at run-time

44

OO Dynamic Binding list is determined at compile time nal choice made at run-time options are organized according to the inheritance hierarchy

44

OO Dynamic Binding list is determined at compile time nal choice made at run-time options are organized according to the inheritance hierarchy determined by the actual type of the object whose member function has been selected

44

In SmallTalk & Java, all function calls are resolved by dynamic binding. In C++, we can choose between compiletime and dynamic binding.

45

2.3.4. Dynamic Binding in C++ A non-inherited function member is subject to dynamic binding if its declaration is preceded by the word virtual.

46

An inherited function member is subject to dynamic binding if that member in the base class is subject to dynamic binding. Using the word virtual in subclasses is optional (but recommended).

47

An inherited function member is subject to dynamic binding if that member in the base class is subject to dynamic binding. Using the word virtual in subclasses is optional (but recommended). Even if a member function is virtual, calls to that member might not be subject to dynamic binding.

47

Dynamically Bound Calls Let foo be a virtual function member. x.foo(), where x is an object, is bound at compile time (static) x.foo(), where x is a reference to an object, is bound at run-time (dynamic). x->foo(), where x is a pointer, is bound at run-time (dynamic).

48

class Animal { public : v i r t u a l S t r i n g eats ( ) { return ??? ; } S t r i n g name ( ) { r e t u r n Animal ; } };

class H e r b i v o r e : public Animal { public : v i r t u a l S t r i n g eats ( ) { return p l a n t s S t r i n g name ( ) { r e t u r n H e r b i v o r e ; } }; 49

class Ruminants : public H e r b i v o r e { public : v i r t u a l S t r i n g e a t s ( ) { r e t u r n grass S t r i n g name ( ) { r e t u r n Ruminant ; } }; class C a r n i v o r e : public Animal { public : v i r t u a l S t r i n g e a t s ( ) { r e t u r n meat S t r i n g name ( ) { r e t u r n C a r n i v o r e ; } }; 50

void show ( S t r i n g s1 , S t r i n g s2 ) { c o u t << s1 << << s2 << e n d l ; }

51

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( a . name ( ) , a . e a t s ( ) ) ; show ( pa>name ( ) , pa>e a t s ( ) ) ; show ( h . name ( ) , h . e a t s ( ) ) ; show ( ph>name ( ) , ph>e a t s ( ) ) ; show ( pah>name ( ) , pah>e a t s ( ) ) ; show ( par>name ( ) , par>e a t s ( ) ) ; 52

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( a . name ( ) , a . e a t s ( ) ) ;

53

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( a . name ( ) , a . e a t s ( ) ) ; / / Animal ???

53

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( a . name ( ) , a . e a t s ( ) ) ; / / Animal ??? show ( pa>name ( ) , pa>e a t s ( ) ) ;

53

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( a . name ( ) , a . e a t s ( ) ) ; / / Animal ??? show ( pa>name ( ) , pa>e a t s ( ) ) ; / / Animal ???

53

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( h . name ( ) , h . e a t s ( ) ) ;

54

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( h . name ( ) , h . e a t s ( ) ) ; / / Herbivore plants

54

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( h . name ( ) , h . e a t s ( ) ) ; / / Herbivore plants show ( ph>name ( ) , ph>e a t s ( ) ) ;

54

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( h . name ( ) , h . e a t s ( ) ) ; / / Herbivore plants show ( ph>name ( ) , ph>e a t s ( ) ) ; / / Herbivore plants

54

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( pah>name ( ) , pah>e a t s ( ) ) ;

55

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( pah>name ( ) , pah>e a t s ( ) ) ; / / Animal plants

55

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( pah>name ( ) , pah>e a t s ( ) ) ; / / Animal plants show ( par>name ( ) , par>e a t s ( ) ) ;

55

Animal a , pa , pah , par ; H e r b i v o r e h , ph ; Ruminant r ; pa = & a ; ph = & h ; pah = & h ; par = & r ; show ( pah>name ( ) , / / Animal show ( par>name ( ) , / / Animal pah>e a t s ( ) ) ; plants par>e a t s ( ) ) ; grass

55

3. Working With Inheritance


Example: Shapes A Picture contains a list of Shapes and information on the size of the picture. Every Shape has a center point and a bounding rectangle.

56

First, some utility classes:


struct Point { double x , y ; }; s t r u c t Rect { Point ul , l r ; void merge ( const Rect & r ) { u l . x = min ( u l . x , r . u l . x ) ; u l . y = min ( u l . y , r . u l . y ) ; 57

l r . x = max ( l r . x , r . l r . x ) ; l r . y = max ( l r . y , r . l r . y ) ; } };

58

class Shape { public : Shape ( ) ; v i r t u a l Shape ( ) ; v i r t u a l void draw ( ) const ; v i r t u a l void zoom ( double f a c t o r ) ; v i r t u a l const P o i n t c e n t e r ( ) const ; v i r t u a l const Rect bound ( ) const ; };

59

picture

60

s t r u c t ShapeList { Shape shape ; ShapeList n e x t ; };

61

class P i c t u r e { public : Picture ( ) ; virtual Picture ( ) ; void c l e a r ( ) ; void add ( const Shape & ) ; Rect bound ( ) const ; void draw ( ) const ;

62

void zoom ( double f a c t o r ) ; private : ShapeList shapes ; };

63

class C i r c l e : public Shape { Point center ; double r a d i u s ; public : C i r c l e ( P o i n t c e n t , double r ) ; C i r c l e ( const C i r c l e & ) ; Circle ( ) ; void draw ( ) const ; void zoom ( double f a c t o r ) ; Rect bound ( ) const ; 64

};

65

class L i n e : public Shape { Point ul , l r ; public : L i n e ( P o i n t p1 , double p2 ) ; L i n e ( const L i n e & ) ; Line ( ) ; void draw ( ) const ; void zoom ( double f a c t o r ) ; Rect bound ( ) const ; }; 66

Drawing a picture:
void P i c t u r e : : draw ( ) const { Shape s = shapes ; while ( s ! = 0 ) { s>shape>draw ( ) ; s = s>n e x t ; } }

Relies on dynamic binding of draw().


67

Without dynamic binding, this would have been written as


void P i c t u r e : : draw ( ) const { Shape s = shapes ; while ( s ! = 0 ) { switch ( s>t a g ) { case l i n e T a g : drawLine ( s ) ; break ; case c i r c l e T a g : d r a w C i r c l e ( s ) ; break ; 68

. . . } s = s>n e x t ; } }

69

Moving to OOP A key marker in OOP style is the replacement of unions (variant records) multi-way branches by dynamic binding over an inheritance hierarchy.

70

Lets look at whats involved in computing the size of a picture:


Rect C i r c l e : : bound ( ) { Rect b ; b . ul . x = center . x b . ul . y = center . y b . l r . x = center . x + b . l r . y = center . y + return b ; }

radius ; radius ; radius ; radius ;

71

Rect L i n e : : bound ( ) { Rect b ; b . ul = ul ; b. lr = lr ; return b ; }

72

Rect P i c t u r e : : bound ( ) const { Shape s = shapes ; if (s != 0) { Rect r = s>shape>bound ( ) ; s = s>n e x t ; while ( s ! = 0 ) { r . merge ( s>shape>bound ( ) ) ; s = s>n e x t ; } } 73

Relies on dynamic binding of bound().

74

Whats involved in adding a new shape (e.g., ellipse)? In traditional languages, design new Ellipse type. Must supply ellipse-specic code for drawEllipse(), boundEllipse(), etc. ...

75

... Find all code everywhere (Picture plus applications) that switches based on tags. add a new case to that code

76

Whats involved in adding a new shape (e.g., ellipse)? In OOPL, design new Ellipse class. Subclass of Shape Must supply ellipse-specic code for draw(), bound(), etc. No changes to Picture required

77

4. Some OOP Languages


OOP in C++ OOP in Java OOP in Smalltalk OOP in Modula 3

78

4.1. OOP in C++


Weve seen the basics already. C++ is a hybrid language. Not all types are classes. Not all class member functions dynamically bound. Inheritance hierarchies tend to be small and special-purpose.
79

4.1.1. Abstract Classes Sometimes we present class interfaces that are intended only as interfaces no implementation is expected.
class Shape { public : Shape ( ) ; v i r t u a l Shape ( ) ; v i r t u a l void draw ( ) const ; v i r t u a l void zoom ( double f a c t o r ) ; 80

v i r t u a l const P o i n t c e n t e r ( ) const ; v i r t u a l const Rect bound ( ) const ; };

81

Cant really provide meaningful code for draw(), bound(), etc. Rather than provide bogus code for the operations, we mark them as abstract. No bodies provided for abstract functions Abstract classes cannot be instantiated as an actual object. The implementation is done in a subclass.
82

class Shape { public : Shape ( ) ; v i r t u a l Shape ( ) ; v i r t u a l void draw ( ) const = 0 ; v i r t u a l void zoom ( double f a c t o r ) = 0 v i r t u a l const P o i n t c e n t e r ( ) const = 0 ; v i r t u a l const Rect bound ( ) const = 0 ; };

83

4.2. OOP in Java


Another hybrid, but purer than C++. Not all types are classes. All class member functions are dynamically bound. All classes organized into a single inheritance tree Garbage collection
84

C++-like syntax

85

Java implementation of Shapes is very similar to C++:


class P o i n t { double x , y ; } class Rect { Point ul , l r ; void merge ( Rect r ) { u l . x = min ( u l . x , r . u l . x ) ; u l . y = min ( u l . y , r . u l . y ) ; 86

l r . x = max ( l r . x , r . l r . x ) ; l r . y = max ( l r . y , r . l r . y ) ; } }

87

abstract class Shape { a b s t r a c t void draw ( ) ; a b s t r a c t void zoom ( double f a c t o r ) ; abstract Point center ( ) ; a b s t r a c t Rect bound ( ) const ; }

Establishes the common interface for all shapes.

88

class ShapeList { Shape shape ; ShapeList n e x t ; };

Since all class objects are assigned by reference, no need for explicit pointers.

89

class P i c t u r e { p r i v a t e ShapeList shapes ; Picture ( ) {. . . }

void c l e a r ( ) { . . . } void add ( const Shape s ) { ShapeList newNode = new ShapeList ; newNode . shape = s ; newNode . n e x t = shapes ; shapes = newNode ; 90

} Rect bound ( ) { . . . } void draw ( ) { . . . } void zoom ( double f a c t o r ) { . . . } };

91

class C i r c l e extends Shape { private Point center ; p r i v a t e double r a d i u s ; C i r c l e ( P o i n t c e n t , double r ) { . . . } void draw ( ) { . . . } void zoom ( double f a c t o r ) { . . . } Rect bound ( ) { . . . } };

92

Drawing a picture:
class P i c t u r e { . . . void draw ( ) { { Shape s = shapes ; while ( s ! = n u l l ) { s . shape . draw ( ) ; s = s . next ; } } 93

94

4.3. OOP in Smalltalk


Smalltalk is both a language and a GUI development environment. In many ways, this is the language that kicked off the OO boom. interpreted (usually) Everything is an object. (Even classes are objects!) All function calls are resolved dynamically.
95

All classes are arranged into a single inheritance tree:

96

O bject

Class

Magnitude

Collection

Char

Number

Point Set Keyed Collection

Integer

Float

Fraction

97

AShape s u b c l a s s : # Rectangle instanceVariableNames : t h e H e i g h t theWidth classVariableNames : setHeight : anInteger set the height of a rectangle theHeight : = anInteger setWidth : anInteger set the width of a rectangle 98

theWidth

anInteger

99

height r e t u r n the height of a rectangle theHeight width r e t u r n the width of a rectangle theWidth

100

draw draw t h e r e c t a n g l e | aLine u p p e r L e f t C o r n e r | aLine : = L i n e new . upperLeftCorner : = t h e C e n t e r x ( theWidth / 2 ) @ ( theCenter y ( theHeight / 2 ) ) .

ARectangle inherits a data member theCenter from AShape. theCenter x means send the x message to the theCenter object.
101

Note the lack of syntactic sugar one seldom really looks at listings of an entire class Variables are weakly typed. Automatic garbage collection

102

A SmallTalk Browser Graphics Array insertion Collections Bag removal Numerics FIFOQueue testing System Set printing add: x Adds x to the end of the queue size := size + 1. dataArray at: size put: x.

add: addAll:

103

104

4.4. OOP in Modula 3


In the Pascal/Modula 2 tradition. kept Pascal/Modula 2 style syntax and emphasis on simplicity adopted C-like (structural equivalance) type system Modularity separate from type declaration garbage collection by default on all pointers
105

programmer can exempt selected classes from garbage collection (for efciency) avail of garbage collection simplies language and code much less emphasis on constructors & destructors

106

INTERFACE Stack ; TYPE T < : REFANY; PROCEDURE Pop (VAR s : T ) : REAL; PROCEDURE Push (VAR s : T ; x : REAL ) ; PROCEDURE Create ( ) : T ; END Stack .

This is a module Stack that declares a class Stack.T


107

<: is the inherits from operator The code of the procedure bodies is very Pascal-like.

108

5. Implementing OO
How are inheritance, dynamic dispatching, etc., implemented?

109

5.1. Implementing and Subtyping

Inheritance

Inheritance of data members is achieved by treating all new members as extensions of the base class:
s t r u c t DLLBase { DLLBase backward ; DLLBase f o r w a r d ; }; 110

s t r u c t Node : public DLLBase { s t r i n g data ; };

111

Extension Inherited members occur at the same byte offset as in the base class: Node 0 backward DLLBase 4 forward 0 backward 8 4 forward data p->forward can translate the same whether p points to a DLLBase or a Node.
112

Assignment & Subtyping This implementation explains why, in languages with copy semantics assignments, we can do
superObj = subObj ;

but not
subObj = superObj ;

113

class Person { public : s t r i n g name ; long i d ; }; class Student : public Person { public : s t r i n g school ; }

114

jones 111110

smith 456782 ODU

115

jones 111110

smith 456782 ODU

jones = smith ;

115

jones 111110

smith 456782 ODU

jones = smith ;
smith 456782 smith 456782 ODU

115

jones 111110

smith 456782 ODU

116

jones 111110

smith 456782 ODU

smith = jones ;

116

jones 111110

smith 456782 ODU

smith = jones ;
jones 111110 jones 111110 x!@z-

116

5.2. Implementing Dynamic Binding


Single Dispatching VTables

117

Single Dispatching Almost all OO languages, including C++, offer a single dispatch model of message passing: the dynamic binding is resolved according to the type of the single object to which the message was sent (dispatched).

118

Single Dispatching (cont.) In C++, this is the object on the left in a call: obj.foo(...) There are times when this is inappropriate. But it leads to a fast, simple implementation

119

Each object with 1 or more virtual functions has a hidden data member. a pointer to a VTable for its class this member is always at a predictable location (e.g., start or end of the object Each virtual function in a class is assigned a unique, consecutive index number.

120

(VTable)[i] is the address of the classs method for the ith virtual function.

121

class A { public: A(); virtual void foo(); virtual void bar(); };

class B: public A { public: B(); virtual void foo(); virtual void baz(); };

A b = ( rand ( ) % 2 ) ? new A : new B ; b>f o o ( ) ;

foo(), bar(), and baz() are assigned indices 0, 1, and 2, respectively.

122

a1

A::foo() A:bar()

b1

a2

B::foo() A:bar() B:baz()

The call b->foo() is translated as


( b>VTABLE [ 0 ] ) ( ) ;

123

Vous aimerez peut-être aussi