Inheritance and Subtypes Inheritance Hierarchies provide us with
Inheritance and Subtypes • Inheritance Hierarchies provide us with a way to represent how objects should be classified, or partitioned into coherent groups. Classification is hard. • Carl Linnaeus is the prototypical classifier, responsible for the taxonomy of living organism with which we are familiar (Kingdom, Phylum, Class, Order, Family, Genus, Species). • Unfortunately, the word inheritance is ambiguous, we talk about inheriting genetic features from our parents, but also speak of inheriting land, paintings, etc. Neither of these quite captures the use of the work inheritance in OOP. • O-O inheritance identifies the possession of common properties because of membership in a class much as the Linnaean hierarchy does. Thus, Mammalia inherits the property that each of its members has a backbone from the Phylum Chordata. Note that there are no direct instances of Chordata that are just Chordates and not mammals, or fish, etc. But the class of mammals inherits this property from its superclass the class of chordates. Lecture #12 PLP Spring 2004, UF CISE 1
Subclass Example public class Queue { public void enqueue(int x) { … } public void dequeue() { … } public int front() { … } public boolean empty() { … } } • • public class Dequeue extends Queue { public void addfront(int x) { … } public void delete. Rear() { … } } Note that unlike in the Linnaean hierarchy, we may have objects that are Queues and other Objects that are Dequeues (my preferred spelling, sorry). Queue q; Dequeue d; d = new Dequeue(); q = d; // OK! Every object that is a dequeue is also a queue d = q; d = (Dequeue)q; // BAD! Not every queue is a dequeue // OK! This asks for a runtime check to // see that this queue is a dequeue. Lecture #12 PLP Spring 2004, UF CISE 2
Method Overriding • A subclass of some class may have a very specific way it needs to do something that objects belonging to the superclass already know how to do. This may be done because extra information needs to be stored, or because there is a very efficient way to carry out the operation on subclass objects, or for other reasons. • Providing a new definition of the method in a subclass gets this done. • Example: to_string (which is defined in the class Object, which is an ancestor class of every Java class) is called by System. out. println to find the string representation of an object to be printed. The default to_string is pretty ugly. You can define a better one if you’ve defined a new class. The new definition overrides the old one. • Warning: C++ only gives fully correct overriding behavior in certain circumstances. – Overriding will occur when referring to an object by a superclass pointer or reference only if the method is declared virtual. – Assigning an object to an ancestor variable (rather than to a pointer or passing as a reference argument) will convert the object into an object belonging to the ancestor class, and its special features will no longer be available. Lecture #12 PLP Spring 2004, UF CISE 3
Abstract Methods and Classes • Suppose we’ve identified the classes Point, Circle, and Rectangle, then we realize we have a general concept Closed. Figure for which we want to declare a class. • Suppose furthermore that one of the methods to be defined for Closed. Figures is area, but we don’t know how to implement area in general, it needs a specific definition. • Then our Closed. Figure class needs to be defined as follows: public abstract class Closed. Figure { … public abstract double area(); … } • The abstract method must be overridden in any non-abstract descendent class of Closed. Figure. • The declaration that Closed. Figure is abstract means that we cannot instantiate any objects that are direct instances of Closed. Figure, that is, ones that don’t belong to some non-abstract subclass of Closed. Figure. Lecture #12 PLP Spring 2004, UF CISE 4
Constructor Superclass Delegation • If we have a superclass that has some interesting properties that are handled at construction time, we may need to delegate it the task of initializing objects belonging to the subclass: public class Rectangle extends Closed. Figure { public Rectange (Point c, double w, double h) { super(c); width = w; height = h; } } • Louden mentions that an alternative is to allow the initialization to be performed in the subclass, however, this is definitely inferior as it imposes on the subclass designer the requirement that they know everything that needs to be done to initialize a superclass object. Lecture #12 PLP Spring 2004, UF CISE 5
Multiple Inheritance (MI) • Stroustrup has been quoted as saying that multiple inheritance is not hard to implement as long as you are willing to define what you mean by it. The problem is not in implementation, but in getting agreement about how it should be done. • Consider the case of two classes Closed. Figure, describing close figures, and Drawable, describing things that can be drawn. I want to define a new class Drawable. Closed. Figure that has all the properties of each of these classes. • Unfortunately, Java only takes me part way. They will allow me to specify an Interface for one of these classes, and then force me to implement special versions of the functions that appear in the interface and replicate any instance variables in a class that implements that interface. This means more redundant implementation and possible introduction of error. That’s not good. Lecture #12 PLP Spring 2004, UF CISE 6
Dynamic Binding in OOP • Dynamic (runtime) Binding (association of a name to a thing). • The key role of dynamic binding in OO is to allow the binding of a method definition to an object variable to be done at run time, so that the most specific method will be executed. • If one takes dynamic binding to its logical extreme, one can construct new classes at run time and perhaps modify existing classes, adding instance variables and methods, while a program is running. • Such dynamic capabilities place a heavy burden on storage management and, as a result, most OO languages include a garbage collector to provide automatic storage management. Lecture #12 PLP Spring 2004, UF CISE 7
Implicit vs. Explicit Dynamic Binding • In Java, the dynamic binding of methods to object variables is implicit. It happens for free. • In C++, one can choose whether or not to have dynamic or static binding. If a method is declared virtual, then it uses a dynamic binding approach. If not, static binding is employed. • Consult the example of page 432. Lecture #12 PLP Spring 2004, UF CISE 8
Smalltalk • Smalltalk was implemented for the ambitious Dynabook Project, a project to make a notebook computer that would do everything you needed started by Xerox PARC in the 1970 s. • Steve Jobs visited Xerox during that period and got ideas that were implementing in the Lisa and Macintosh. • Smalltalk 80 was the first mainstream version of Smalltalk, but it suffered from having limited distribution, requiring expensive hardware (including a mouse and graphics display), and was built around a programming environment that was quite large and somewhat slow. A similar remark could be made of the LISP machines of the time such as Symbolics offered. These machines were ahead of the curve and put too great a demand on the hardware of the day to be immediately accepted in a wide circle. Lecture #12 PLP Spring 2004, UF CISE 9
Smalltalk Class Hierarchy • Smalltalk has a single-rooted class hierarchy, and everything that a program can manipulate belongs to a class. Object Udefined. Object Boolean True Fase Magnitude Char Number … Fracton Lecture #12 Collection Set … Integer Float PLP Spring 2004, UF CISE 10
- Slides: 10