160 likes | 284 Views
Dynamic Binding. Object-Oriented Programming 236703 Spring 2008. Non-Strict Inheritance. AKA Inheritance More Powerful Abstraction Mechanism: a subclass is just like the superclass, except for an explicit list of changes: Additional operations. Additional structure elements.
E N D
Dynamic Binding Object-Oriented Programming 236703 Spring 2008
Non-Strict Inheritance • AKA Inheritance • More Powerful Abstraction Mechanism: a subclass is just like the superclass, except for an explicit list of changes: • Additional operations. • Additional structure elements. • Operations implemented differently, also called overridden operations. • Note: there is usually no way to “re-implement” structure elements.
Binding Time • Binding: linking between messages and methods • Compile Time • Link Time • Execution Time: • Program Init • Procedure/function begin • Statement Execution • Inclusion Polymorphism: The same entity may refer to objects of different classes, each of which has a different implementation of the same method • Inclusion Polymorphism + Overriding = Binding Question • Static Binding (AKA Early Binding): the compiler uses the type of variables to do the binding at a compile (link) time • Dynamic Binding (AKA Late Binding): the decision is made at run time based on the type of the actual values
Manager print++ Static vs. Dynamic Types Employee print+ • Consider the call: Employee* e = new Manager(); e->print(); • What is the type of e? • Static Type: Employee * • What can be determined in compile time • Dynamic Type: Manager * • Actual type, as determined in run time • Which version of print will be called? • Based on the static type? or, • Based on the dynamic type?
Dynamic Binding and Static Typing • Static typing: guarantee that a method exists • A variable of type T can contain only objects of type T, or of type T', where T' is derived from T. • A message to an object is legal only if its static type recognizes it. • Dynamic binding: make sure that the right method is selected. • The method invoked for an object depends on its dynamic type. • Static typing + Dynamic binding: the right combination of safety and power • Examples: Eiffel, C++, Java, Object-Pascal, Turbo-Pascal, etc.
C++ Example struct Base {virtualvoid f() { ... } void g() { ...} }; struct Derived: Base {virtualvoid f() { ...} // Override f() of Base void g() { ...} // Override g() of Base void h() { ...} } y; Base *px = &y; px->f(); // The right methodpx->g(); // The wrong methodpx->h(); // Compile time error! No guarantee that the method exists
Java Example publicclass X { public String toString() { return "X"; } publicfinalintaddThree(int n) {return n+3; } publicstaticintmul(int a, int b) {return a*b; } } publicclass Y extends X { publicfinal String toString() { return "Y" + super.toString(); } { What's the binding of super.toString()? X x = new X(); x.toString(); x.addThree(5); x.mul(3,9); Y y = new Y(); y.toString(); y.addThree(5); y.mul(3,9); X x = new Y(); x.toString(); x.addThree(5); x.mul(3,9);
Downcasting vs. Dynamic Binding void draw(Shape *p){ if (Circle *q = dynamic_cast<Circle *>p) { // Draw circle ... } else if (Line *q = dynamic_cast<Line *>p) { // Draw line ... } else if (Rectangle *q = dynamic_cast<Rectangle *>p) { // Draw rectangle ... } ... } RTTI considered harmful: • Order of classes in the if chains is significant • Module must change whenever new class is added to the hierarchy
Forms of Overriding • Replacement: The new implementation of an operation replaces the implementation of the operation in the base class. • The only kind of overriding in earlier versions of Eiffel. • Refinement: The new implementation of an operation refines the implementation of the operation in the base class. It reuses the code of the overridden method. • Usually: • Overriding method calls inherited method • Just like using: • super in Smalltalk, Java • Inherited in Turbo-Pascal 7.0 • Precursorin Eiffel
Kinds of Refinement • Alpha refinement: the overriding operation calls the overridden operation. • C++, Smalltalk, Java ... • Beta refinement: the overridden operation must call the overriding version explicitly. • Excludes replacement! If the implementation in the superclass does not execute an inner command, then the implementation in the subclass is not executed. • Better guarantee of conformance. • Simula, BETA.
Alpha Refinement and Subobjects • Recall that each object of a subclass has a subobject of the superclass. • This subobject may have in turn other sub-subobjects in it. • Alpha refinement involves a forwarding of the message to the subobject. • Mechanisms for forwarding to subobject: • Eiffel: None. Code must be copied. • Smalltalk and Objective-C: super pseudo-variable refers to largest contained subobject. • Object and Turbo Pascal: Inherited keyword refers to the class in which the overridden method was defined. • C++: Must use scope resolution operator explicitly class CheckedArray: public Array { ... explicit CheckedArray(int len): Array(len) {} ... };
Beta Refinement • Advantage: The working of the subclass bears more resemblance with that of the superclass. • Disadvantages: • The designer of an overriding method must be intimately familiar with the workings of the overridden method. • The inner keyword cannot be overridden. • Pseudo C++ Examples: struct Window { virtual void draw(void) { ... // Set clipping region inner; ... // Restore clipping region } }; struct Object { virtual bool print(void) { if (inner) return; cout << "an object"; return false; } };
Beta Refinement in Flavors • before and after daemons: • Called before and after the overriding method • The more general ones daemons wrap around the more specific ones, with the primary method, in the middle • It is possible, in principle, to define daemons also for daemons! • Example: FramedWindowsubclassOf: Window methods: after draw [self drawFrame] TitledFrameWindowsubclassOf: FramedWindow methods: after draw [self drawTitle]
Alpha Refinement a-la Flavors • Wrappers: • Just like daemons, but defined in the subclass. • More powerful than supersince multiple wrappers will nest appropriately, even if an overriding method down the inheritance hierarchy fails to invoke the overridden method. • Main drawback: • Confusing semantics!
Programmer Defined Combination In Flavors, it is possible to define a method combination facility, using the full generality of Lisp: Class: Military ...methods: generic totalFuelSupply: fuelType [methodCombination: sum] totalFuelSupply: fuelType [ ... ] Class: ArmysubclassOf: Military methods: totalFuelSupply: fuelType [ ... ]