C Sharp
C Sharp
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.
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
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
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
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
17
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
21
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
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
30
31
Adams Baker
Cook
32
33
34
35
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
when is the decision made as to what code will be executed for this call to foo?
39
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
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
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 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
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
56
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
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
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 ; } }
. . . } 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
71
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
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
78
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
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
C++-like syntax
85
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 ; }
88
Since all class objects are assigned by reference, no need for explicit pointers.
89
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
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
96
O bject
Class
Magnitude
Collection
Char
Number
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
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
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 .
<: 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
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
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
115
jones 111110
jones = smith ;
115
jones 111110
jones = smith ;
smith 456782 smith 456782 ODU
115
jones 111110
116
jones 111110
smith = jones ;
116
jones 111110
smith = jones ;
jones 111110 jones 111110 x!@z-
116
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 B: public A { public: B(); virtual void foo(); virtual void baz(); };
122
a1
A::foo() A:bar()
b1
a2
123