You are on page 1of 15

Dynamic Binding

Object-Oriented Programming 236703 Spring 2008


1

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

Static vs. Dynamic Types


Consider the call:
Employee* e->print(); e = new Manager(); Employee print+

What is the type of e?


Static Type:
Employee * What can be determined in compile time Manager * Actual type, as determined in run time

Manager print++

Dynamic Type:

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, TurboPascal, etc.

C++ Example
struct Base { virtual void f() { ... } void g() { ...} }; struct Derived: Base { virtual void f() { ...} // Override f() of Base void g() { ...} // Override g() of Base void h() { ...} } y; Base *px = &y; px->f(); // The right method px->g(); // The wrong method px->h(); // Compile time error! No guarantee that the method exists

Java Example
public class X { public String toString() { return "X"; } public final int addThree(int n) {return n+3; } public static int mul(int a, int b) {return a*b; } } public class Y extends X { public final 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 Precursor in 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:
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. Eiffel: Precursor keyword. C++: Must use scope resolution operator explicitly class CheckedArray: public Array { ... explicit CheckedArray(int len): Array(len) {} ... };

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.

Beta Refinement

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: FramedWindow subclassOf: Window methods: after draw [self drawFrame] TitledFrameWindow subclassOf: FramedWindow methods: after draw [self drawTitle]

Alpha Refinement a-la Flavors


Wrappers:
Just like daemons, but defined in the subclass. More powerful than super since 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: Army subclassOf: Military methods: totalFuelSupply: fuelType [ ... ]