Strict Inheritance Object-Oriented Programming 236703 Winter 2014-5 1 1
Abstractions Reminder A class is an abstraction over objects A class hierarchy is an abstraction over classes Similar parts of different classes can be joined Inheritance forms class hierarchies Yet another case where abstraction matches the way we think Inheritance serves two purposes: 1. Model the is a relation 2. Save code duplication Avoid #2 if #1 doesn t apply! 2
Polymorphism Reminder Poly many, morph form Yet another abstraction mechanism Separate appearance from implementation In dynamic languages always In static languages relies on inheritance 3
Varieties of Polymorphism Polymorphism Ad-hoc Universal Coercion Overloading Inclusion Sub-type Parametric 4
Ad hoc vs. Universal Polymorphism Ad hoc: Polymorphism is over finitely few shapes: often, very few. Different shapes are generated manually, or semimanually. No unifying common ground to all shapes, other than designer s intentions. Uniformity is a coincidence, not a rule. Overloading: double max(double d1, double d2); const char* max(const char* s1, const char s2); Coercion: int i = 3.141; 5
Ad hoc vs. Universal Polymorphism Universal: Polymorphism is over infinitely many types. There is a unifying, common ground to all the different shapes the polymorphic entity may take. Parametric template<t> void Sort(T list)... Inclusion Base* b = new Derived; 6
Strict Inheritance New abstraction mechanism: extend a given class without touching its code. Conformance (AKA substitutability) If a class B inherits from another class A, then the objects of B can be used wherever the objects of A are used. 7
Strict Inheritance Benefits of strict inheritance: No performance penalty Compile-time creature No conceptual penalty Structured path for understanding the classes Drawbacks of strict inheritance: Not overly powerful! 8
Strict Inheritance and the Different Structure Parts of a Class The structure of the derived class is an extension of that of the base class Protocol The derived class is a subtype of the base class Behavior The derived class implements only the new protocol elements Forge Mill The derived class has a new forge The derived class has a new mill Usually, must invoke the mill of the base class. 9 9
Inclusion Polymorphism and OOP Suppose that the function fire() expects an instance of class Employee. Then, it will also accept an instance of class Manager, provided that Manager (strictly) inherits from Employee. Manager has everything Employee has (in exactly the same form!) The additional operations in Manager will not be used in fire() We say that the type Manager is a subtype of the type Employee. We say that the type Employee includes the type Manager. The polymorphism in this case is a result of subtyping, or type inclusion. 10
Employee e; Manager m; Polymorphic Methods e.raise_salary(10); // OK m.raise_salary(10); // OK e.is_manager_of(...); // Error m.is_manager_of(e); // OK The code of the raise_salary method is Polymorphic It takes a this of various types It can be applied to all subtypes of Employee. Without polymorphism, inheritance makes very little sense. Could just as well use composition 11 Employee raise_salary Manager is_manager_of
Polymorphic Objects All variables in Smalltalk are polymorphic. They may store instances of all classes. this is a polymorphic object. It may point to things of different subtypes at different times. A pointer to an inherited type is generated whenever an inherited method is called. In fact, all class pointers and all class references in C++ are polymorphic... 12
Pointers as Polymorphic Objects Employee e, *pe; Manager m, *pm; pe pm E M Employee Manager Rules for pointer mixing: pe = &e; // OK - Ordinary C type rules pm = &m; // OK - Ordinary C type rules pe = &m; // OK - Pointers are polymorphic! pm = &e; // Compile time error 13
References as Polymorphic Objects E M Employee Manager ostream& operator<<(ostream&,const Employee&); Employee e; Manager m; Employee& eref1 = e; // OK! Employee& eref2 = m; // OK! Reference to subobject Manager& mref1 = e; // Compile time error! Manager& mref2 = m; // OK! cout << e << m; // OK! Reference to subobject 14
Up-Casting Casting: A synonym for coercion from a derived type to the base type. Up-casting: casting pointers up the inheritance hierarchy. Up-casting of this occurs implicitly whenever an inherited method is called. Employee e; Manager m; m.is_manager_of(e); // Type of this is Manager *. // No casting takes place Employee raise_salary Manager is_manager_of m.raise_salary(10); // Type of this is Employee * // in raise_salary // Up casting must take place 15
Down-Casting Down-Casting: casting pointers and references down the inheritance hierarchy: Must be done explicitly. Employee e, *pe; Manager m, *pm; pe = &m; m = *pe; // explicit down casting: // OK: implicit upcasting. // error: implicit downcasting is not allowed pm = (Manager*)pE; // deprecated syntax pm = static_cast<manager*>pe; // recommended syntax pe // either way, you better know what you are doing! E M Employee Manager 16
Value Semantics, Coercion & Polymorphism Polymorphism is applicable to code and variables but not to values. Coercion: translation from a value of one type to a value of a different type. Often with some loss of contents. Example: coercion from integer to real and vice versa. Inheritance in C++: defines a coercion from the derived class to the base class. All subtypes can be coerced to base type Coercion is done by extracting the subobject. 17
class Base { //... }; What are Subobjects? class Derived : public Base { //... }; Each object of class Derived has a subobject of class Base It is possible in many cases to relate to that subobject 18
Rules for Mixing Values Employee e; Manager m; Mixing Values E M Employee m = e; // Error - No coercion is defined. // Manager is an Employee but not vice-versa! e = m; // OK - Valid coercion: truncation will occur. Manager 1. Call the (compiler generated) type casting operator from Manager to Employee 2. Call the (compiler-defined or user-defined) Employee to Employee assignment operator. 19
Arrays of Values Employee department[10]; Manager management[10]; department and management are not compatible in any way. In general, sizeof Employee <= sizeof Manager Usually, sizeof Employee < sizeof Manager Therefore, an array of managers (usually) occupies more space than an array of the same size of employees, and the conversion between the two is not trivial. This is just like an array of char which is not compatible at all with an array of int Although char and int are compatible in some operations. 20
Arrays of Pointers It is often convenient to define mixed type collections. The simplest and easiest way to do so is to use an array of pointers to the base class. Employee* department[100]; It is easy to deposit objects into the above array, however, determining the type of object that resides in a certain location requires down casting. Down casting should be used only in extremely special cases. In this common situation, what should be used instead is dynamic binding. 21
Java Array Subtyping In Java, if class Manager is a subtype of class Employee, then Manager[] is a subtype of Employee[]: Employee ee[]; Manager mm[]; Manager[] marr = new Manager[10]; Employee[] earr = marr; // OK earr[0] = new Employee(); // compiles, but run-time error // ArrayStoreException thrown 22