Summary of Class Presentation for June 21, 1999 Topic: Composition and Inheritance Composition and inheritance are complementary methods for achieving significant code reuse. Composition involves declaring and defining one or more objects of other classes as data fields within an object of the base class. The base class object is then able to call methods of the contained objects to perform tasks as part of the tasks for which the base class object is responsible. Inheritance involves extending an existing base class to produce a derived class. Objects of the derived class then contain all the methods and data fields of the base class as well as any additional methods and data fields their class explicitly defines. Inheritance can be dangerous and lead to hard to maintain programs unless it is controlled. The usual restriction followed by capable professional programmers is called Liskov substitution after Barbara Liskov, a professor at MIT. Liskov substitution imposes the following controls on inheritance: 1. The derived class must support all the methods ( the entire interface) of the base class; 2. the meainings of all methods and data fields inherited from the base class must be preserved in the derived class. When these restrictions are followed, objects of the derived class can serve as members of the base class ( this is called upcasting and will be covered on June 23. When inheritance is done, objects of the derived class actually contain sub-objects of the base class. For example, imagine the following code fragment: class a { data fields f1, f2, and f3 methods m1, and m2 } class b extends a { data fields f4 and f5 methods m3, m4, and m5 } If bb is an object variable of class b and new has been used to create an object that bb references, the storage can be viewed as: bb: handle ( also called reference) to handle for an object of class a f4 f5 reference to access m3, m4, and m5 where the contained handle for an object of class a references f1 f2 f3 m1 m2 Composition and inheritance can be combined in a single program or even a single class. A few miscellaneous notes about inheritance: 1. When an object of a derived class is initialized, the default constructor of the base class is automatically called before the default constructor of the derived class UNLESS 2 is done. 2. This automatic calling of default constructors can be avoided by having the applicable constructor in the derived class start with a call to super, perhaps with parameters. This calls the constructor in the base class with those parameters. This use of super must be the first executable statement in the derived class constructor. 3. If a constructor of the base class is called whether automatically or through the use of super, it is an error, if that constructor does not exist. 4. Unlike C++, overriding a method in a derived class does not mask the method in the base class unless the parameter types of the overriding method exactly match those of the base class method with the same name.