e0844b98f0f74af6e7afb01ace6f9e88.ppt
- Количество слайдов: 42
Chapter 10 - Object-oriented Programming Languages: Principles and Practice, 2 nd Ed. Kenneth C. Louden © Kenneth C. Louden, 2003 1
Why objects? Three fundamental benefits: l Objects give more dynamic control over initialization and the exact behavior of functions that change or report data. l Objects also allow for redefinition of behavior, including extension, that permits significant code reuse. l Redefinition of behavior can work dynamically, so that even recompilation of existing code is unnecessary. (Indeed, some languages, such as Smalltalk, allow behavior to change even during execution!) Chapter 10 K. Louden, Programming Languages 2
Three fundamental concepts support these benefits: l Classes and methods – The class is an ADT mechanism that additionally offers good initialization control (constructors). l Inheritance – A class can extend another class (it becomes a subclass), thus enabling the reuse of all (or some) of the previously-written code. l Dynamic Binding – A variable of a class can contain an object of a subclass, and all subclass-modified behavior automatically applies. Chapter 10 K. Louden, Programming Languages 3
Classes and methods Text contains standard Complex example. l Here is another (similar to java. awt. Point): l public class Point { // constructors: public Point() { x = 0; y = 0; } public Point(double x 0, double y 0) { x = x 0; y = y 0; } // methods: public double get. X() { return x; } public double get. Y() { return y; } public String to. String() { return get. Class(). get. Name() +"[x="+x+", y="+y+"]"; } public void move. By(double dx, double dy) { x = x + dx; y = y + dy; }//data: private double x, y; } Chapter 10 K. Louden, Programming Languages 4
Classes and methods (2) l Sample driver: public class Point. Test { public static void main(String[] args) { Point p = new Point(1, 2); System. out. println(p); p. move. By(1, 1); double r = p. get. X()+p. get. Y(); System. out. println(r); } } l Note use of constructor in call to new: failing to initialize is not an option (q holds no Point at all until new is called). Chapter 10 K. Louden, Programming Languages 5
Classes and methods (3) l l l A class differentiates public from private. Data is almost always private. Methods and constructors are usually public. The implementation, however, is visible in the source code (Java). Constructors allocate memory dynamically. Memory gets freed by a garbage collector (Java). Methods are like functions, except that they must be called on an object: x. f() instead of f(x). Every method has an implicit parameter (this in Java). The emphasis on x rather than f in x. f() is important: x get to "decide" what f means. In Smalltalk, x is "sent the message f". Chapter 10 K. Louden, Programming Languages 6
Inheritance Note that I have already reused some code in Point. Test: System. out. println(p). How is it that println knows how to print a Point, when I only just defined it? ? l The answer is that println calls to. String, which is defined for all objects, and which I redefined in Point to do what I wanted. If I hadn't, the output would have been: Point@ba 34 f 2 l All classes in Java extend Object, and Object has a number of useful methods which should always be redefined: to. String, equals (not done here), and perhaps clone (also not done here). l Chapter 10 K. Louden, Programming Languages 7
Inheritance (2) To show the usefulness of inheritance, let's define a Colored. Point by extending the Point code (using java. awt. Color): public class Colored. Point extends Point { public Colored. Point() { super(); color = Color. white; } public Colored. Point(double x 0, double y 0) { super(x 0, y 0); color = Color. white; } public Colored. Point(double x 0, double y 0, Color c 0) { super(x 0, y 0); color = c 0; } public Color get. Color() { return color; } public void set. Color(Color c) { color = c; } public String to. String() { return super. to. String()+"["+color+"]"; } private Color color; } Chapter 10 K. Louden, Programming Languages 8
Inheritance (3) l Now a Colored. Point inherits all of the behavior of Point, plus it has a color. Note how all the constructors had to be redefined -constructors are not inherited (fine control over initialization). [Exercise: there is a missing constructor. What is it? ] l Superclass constructors also had to be called during initialization (super(x 0, y 0) in line 5). l The to. String method is overridden, giving new behavior (but retaining the old behavior using a call to super. to. String() in 3 rd line from bottom. l Chapter 10 K. Louden, Programming Languages 9
Dynamic Binding l We can demonstrate the new behavior of Colored. Point by changing only the constructor call in Point. Test: Point p = new Colored. Point(1, 2); Now the program prints: Colored. Point[x=1. 0, y=2. 0][java. awt. Color[ r=255, g=255, b=255]] 5. 0 l Dynamic binding says that the new to. String method gets called automatically in println. l A Point variable can hold a Colored. Point, but not vice versa: upcasting is fine, downcasting is not (the subtype principle). l Chapter 10 K. Louden, Programming Languages 10
Privacy revisited l Because the data x and y in Point are private, Colored. Point could not access them directly. Instead, superclass constructors and methods had to be called. l Using protected access for data removes this problem, but at extreme cost: implementation details are accessible. l Failing to include an access specifier is just as bad: it gives "package" protection in Java, which is essentially "local public". Chapter 10 K. Louden, Programming Languages 11
Multiple Inheritance Allows us to combine the public interfaces of two different classes in a single subclass. l Java doesn't have it -- but it has multiple interface inheritance which is almost as powerful, and much easier to implement. l An interface in Java is a class without any implementation (there are no constructors and all methods are implicitly public). l Typical examples: Comparable, Iterator l Chapter 10 K. Louden, Programming Languages 12
Polymorphism Java has two kinds: overloading and subtype polymorphism. The first is static, the second dynamic: class A { int f() { return 1; } int f(int x) { return x+1; } } class B extends A { int f() { return 2; } //dynamic int f(char x) { return x+2; }//static } l Now if A a = new B(), the call a. f('a') returns 98, not 99! l Chapter 10 K. Louden, Programming Languages 13
Polymorphism (2) Java doesn't yet have templates (but may soon), so there is no parametric polymorphism. l Instead, Java uses "based-object" polymorphism to get "generic" behavior: l // any object will do: System. out. println(Object obj) Containers contain Objects, which must be cast back to what we actually put there. l Mistakes are possible, but rare. When they occur, a runtime exception is generated. l Chapter 10 K. Louden, Programming Languages 14
C++ l l l A complex, multiparadigm language. Has almost every conceivable feature. Some of its problems are inherited from C. Programs can be very fast and concise. For OO programming, problems come from (not in order of importance): – – – Multiple inheritance Operator overloading Lack of garbage collection Interaction with templates Focus on execution speed Inadequate standard library Chapter 10 K. Louden, Programming Languages 15
C++ Example (like Java example): #include <string> class Point { public: // constructors: Point(): x(0), y(0) {} Point(double x 0, double y 0): x(x 0), y(y 0){} // methods: ("member functions") double get. X() { return x; } double get. Y() { return y; } std: : string to. String(); void move. By(double dx, double dy) { x = x + dx; y = y + dy; } //data: ("data members") private: double x, y; }; Chapter 10 K. Louden, Programming Languages 16
Notes about previous slide: l Public and private apply to groups of declarations, not single declarations (default is actually private!). Constructors have funny initialization code prior to code block (efficiency issue). l The whole class declaration must be followed by a semicolon (C issue). l Code for to. String method is missing. l Standard string class is called std: : string (part of std namespace, where : : is the scope resolution operator), and must be explicitly accessed via #include (again a C issue). l Chapter 10 K. Louden, Programming Languages 17
Code for Point: : to. String() You can put it anywhere you like in the compile/link path. Common is to put the class def in a. h file and the code in a. cpp (or. CC) file. l Why not put everything in the class definition? Code in the definition is inlined—good only for short, simple code. Also: information hiding. l Here is the code: l std: : string Point: : to. String() { std: : ostringstream ost; ost << "Point[x=" << x << ", y=" << y << "]"; return ost. str(); } Requires the use of an "output" string stream (ostringstream) and the "output" operator << to convert numbers to strings (#include <sstream>) l Note hardwiring of class name. C++ reflection (called RTTI) is system-dependent (pp. 460 -461). l Chapter 10 K. Louden, Programming Languages 18
C++ driver Code: l Driver is always a regular function (not in a class): int main() { Point p = Point(1, 2); std: : cout << p. to. String() << std: : endl; p. move. By(1, 1); double r = p. get. X()+p. get. Y(); std: : cout << r << std: : endl; } Note lack of call to new—so far no dynamic allocation! l "std: : cout <<" is like Java System. out. print (requires #include <iostream>). l But no automatic call to. String, so we have to do it manually. (C++ experts: we could overload << to handle Points, but then no dynamic binding!) l Chapter 10 K. Louden, Programming Languages 19
C++ code for Colored. Point l First, no Color class is available in std. l So let's define a silly one, just for this example: enum Color {white, red, blue, green, yellow}; l A bit like a Java interface with constants: public interface Color { int white = 0; int red = 1; int blue = 2; int green = 3; int yellow = 4; } l Except that it is a real datatype with 5 possible values (which are part of the global namespace and are automatically convertible to integers). Chapter 10 K. Louden, Programming Languages 20
C++ code for Colored. Point (2) l Here now is the class definition: class Colored. Point : public Point { public: Colored. Point(): Point(), color(white){} Colored. Point(double x 0, double y 0) : Point(x 0, y 0), color(white) {} Colored. Point(double x 0, double y 0, Color c 0): Point(x 0, y 0), color(c 0) {} Color get. Color() { return color; } void set. Color(Color c) { color = c; } std: : string to. String(); private: Color color; }; Chapter 10 K. Louden, Programming Languages 21
C++ code for Colored. Point (3) l Here is the code for to. String(): std: : string Colored. Point: : to. String() { std: : ostringstream ost; ost << "Colored" << Point: : to. String() << "[" << color << "]"; return ost. str(); } Note use of a "kludge" to print out the class name, while still calling the superclass to. String() (which must be named explicitly). l Note superclass constructor calls (Point() and Point(x 0, y 0)), which also must be named explicitly. l Note use of public in inheritance: protection can apply—private & protected inheritance exists! l Chapter 10 K. Louden, Programming Languages 22
C++ driver using Colored. Point: l Let's try the Java equivalent, with a single change: int main() { Point p = Colored. Point(1, 2); // new call std: : cout << p. to. String() << std: : endl; p. move. By(1, 1); double r = p. get. X()+p. get. Y(); std: : cout << r << std: : endl; } l Alas, this still prints the same as before: Point[x=1, y=2] 5 l The C++ default is to use no inheritance or dynamic binding features at all—in fact, the constructed Colored. Point is immediately thrown away after a copy of its (Point) data to p! (For C compatibility) Chapter 10 K. Louden, Programming Languages 23
Inheritance & dynamic binding in C++ applies OO features only to pointer and reference variables, not to directly allocated variables (again, for C compatibility). l So let's change p to a pointer (note use of new now, as well as access operator ->): l int main() { Point* p = new Colored. Point(1, 2); std: : cout << p->to. String() << std: : endl; p->move. By(1, 1); double r = p->get. X()+p->get. Y(); std: : cout << r << std: : endl; delete p; // no garbage collection } l Alas, still no change in the output!! Chapter 10 K. Louden, Programming Languages 24
Inheritance/dynamic binding in C++(2) l C++ also insists that methods that are (potentially) to be overridden be marked as virtual (for efficiency). Thus, we need to change the specification of to. String in the base Point class to include the virtual tag (changing it in Colored. Point is not good enough): virtual std: : string to. String(); l Now, finally, we do get the desired output: Colored. Point[x=1, y=2][0] 5 l C++ mantra: you must tell it exactly what you want, or it will act like C. Chapter 10 K. Louden, Programming Languages 25
Polymorphism l C++, like Java, has overloading as well as subtype polymorphism, with the same possibility of confusion: class A { public: virtual }; class B : public: virtual }; l int f() { return 1; } int f(int x) { return x+1; } public A { int f() { return 2; } int f(char x) { return x+2; } Now if A* a = new B(), the call a->f('a') returns 98, not 99, just as in Java. Chapter 10 K. Louden, Programming Languages 26
Polymorphism (2) l C++ also has templates, which are purely static and do not interact directly with the OO features—a Point could be declared over any coordinate type: template <typename T> class Point { public: Point(T x 0, T y 0): x(x 0), y(y 0){} T get. X() { return x; } T get. Y() { return y; } virtual std: : string to. String(); void move. By(T dx, T dy) { x += dx; y += dy; } private: T x, y; }; l There is no predefined relationship between, say, Point<int> and Point<double>; mechanisms to convert between them are possible but tricky. Chapter 10 K. Louden, Programming Languages 27
Multiple inheritance in C++ Unlike Java (and most Smalltalks), C++ has multiple inheritance, which causes significant complications. l Multiple inheritance can take two forms: repeated inheritance and shared inheritance. l Shared inheritance is usually what we want— instances of a superclass that have two access routes are actually the same instance: l Chapter 10 K. Louden, Programming Languages 28
Multiple inheritance in C++ (2) l Repeated inheritance means different paths refer to different objects of the same superclass: The default in C++ is repeated inheritance! l To get shared inheritance, you must use the keyword virtual after the inheritance colon: class A {. . . }; class B : virtual public A {. . . }; class C : virtual public A {. . . }; class D : public B, public C {. . . }; l Chapter 10 K. Louden, Programming Languages 29
Interfaces in C++ has no interfaces as such, but it does have abstract classes (with a partial implementation or none at all—as in Java): class Closed. Figure // an abstract class {public: virtual double area() = 0; . . . }; l The tag "= 0" in C++ indicates that there will be no implementation of the area method in Closed. Figure. l As in Java, you cannot create an instance of an abstract class. l Note that abstract methods must be virtual, since they must be defined in subclasses. l Chapter 10 K. Louden, Programming Languages 30
Smalltalk l l l l Ahead of its time: consistent design and rich library. Dynamic (like Lisp): variables have no specified type. The class structure is the type system. Everything is an object, including numbers. So somewhat lacking in efficiency. There are no explicit protection markers: all data is implicitly private, all methods implicitly public. Syntax is peculiar, and tied to the runtime environment. Typically only a global namespace for classes, so I will call the example class My. Point. Chapter 10 K. Louden, Programming Languages 31
Smalltalk My. Point class l Using the syntax conventions of the text: Class name: My. Point Superclass: Object Instance variables: x y "(data fields)" Methods: get. X x get. Y y move. By: dx and: dy x x + dx. y y + dy to. String (super as. String), '[x=', x as. String, ', y=', y as. String, ']' Note lack of constructors (see later slide). l Special characters: = return, = assignment. l Chapter 10 K. Louden, Programming Languages 32
Smalltalk My. Point class comments Note definition of move. By: dx and: dy Methods that take arguments must have a name ending in a colon (a keyword selector) before every argument. So this method is actually the move. By: and: method. l The period in the move. By: and: code is like a semicolon—it separates (not terminates) statements. l Note use of as. String in code for to. String. Indeed, we should really call this method as. String too. l The comma in the to. String code is the string concatenation operator, and single quotes delimit string literals. l Chapter 10 K. Louden, Programming Languages 33
Smalltalk My. Point constructors Constructors in Smalltalk are class methods: they are sent to the class (which is an object). l There is a predefined constructor named new (with no arguments—like the default constructor), which initializes all instance variables to nil. l new can be redefined (but probably shouldn't), and any other class methods can also be added. l To avoid these complications (and some others not mentioned), we add two initialize methods (which is a standard hack): l initialize x 0. y 0 initialize: x 0 and: y 0 x x 0. y y 0 Chapter 10 K. Louden, Programming Languages 34
Smalltalk My. Point driver I/O is another problem area in Smalltalk, since all execution occurs inside windows, and typically we would have to create a new window to see output. l Inside a workspace (code to execute), all values can be inspected, and we will use this to see the output. l Here is the driver workspace code: l p p r r l My. Point new initialize: 1 and: 2. inspect. to. String inspect. move. By: 1 and: 1. p get. X + p get. Y. inspect The result in a typical Smalltalk system (Squeak) is on the next slide. Chapter 10 K. Louden, Programming Languages 35
Chapter 10 K. Louden, Programming Languages 36
Smalltalk Colored. Point class Class name: Colored. Point Superclass: My. Point Instance variables: color Methods: get. Color color set. Color: c 0 color c 0 initialize super initialize. color Color white initialize: x 0 and: y 0 super initialize: x 0 and: y 0. color Color white initialize: x 0 and: y 0 and: c 0 super initialize: x 0 and: y 0. color c 0 to. String (super to. String), '[color=', color as. String, ']' Chapter 10 K. Louden, Programming Languages 37
Smalltalk Colored. Point, cont'd. l Note calls to super in the previous slide. l Although we don't use it, the this reference is called self in Smalltalk. l Now we change the first line of the driver code to: l Running the driver code produces the picture on the next slide. l Note that, as expected, the result of the to. String method changes from p Colored. Point new initialize: 1 and: 2. 'a My. Point[x=1, y=2]' to 'a Colored. Point[x=1, y=2][color=Color white]' Chapter 10 K. Louden, Programming Languages 38
Chapter 10 K. Louden, Programming Languages 39
OO Implementation Issues l l l Efficiency is a concern since dynamic binding appears to imply a search of the class hierarchy at each call site. Smalltalk in fact does this. Runtime penalty can be mitigated by hashing and extra links. But still significant. Better: compute method table for each class at compile time, with statically fixed offsets for each method. Assign a pointer to it on object creation. Then follow the pointer (one extra indirection plus an offest calculation) at each call site. Variously named VMT, VFT, or just method table (V for virtual). Chapter 10 K. Louden, Programming Languages 40
VMT Example (Java) l A Point object would be laid out in memory as follows (we ignore methods other than to. String that are inherited from Object): l The layout for a Colored. Point would then be: Chapter 10 K. Louden, Programming Languages 41
VMT Example (2) Note how all inherited data and methods stay at the same locations in Colored. Point. l Note that the overriden to. String in Colored. Point goes in the original to. String slot for a Point (indicated by subscripts in the diagrams). l All new features are added at the end using new offsets. l Exercise: describe what happens in the example of slide 13 using VMT diagrams. l Chapter 10 K. Louden, Programming Languages 42
e0844b98f0f74af6e7afb01ace6f9e88.ppt