Summary of Class Presentation for June 28, 1999 Topics: Constructors and Polymorphism, downcasting This is the last new material before the examination on Wednesday. When a class inherits from another class, the order of constructor calls is: 1. The storage for the object is initialized to default values ( 0 for numerical types, null character for char, false for boolean, null reference for object variables); 2. The base class constructor is called. This constructor is the default constructor unless the first statement in the derived class constructor is super with parameters. In that case, the base class constructor is called that has parameter types matching the types of the values given on the super statement; 3. Step 2 is repeated recursively such that the root of the inheritance hierarchy is constructed first, followed by its immediate child, then that child's child class and so on until the current class; 4. At each level in this recursive call, member initializers are called for any objects contained within objects of this class ( composition). These are called in the order that the members are declared; 5. The body of the derived-class constructor is executed. For example, suppose class D inherits from class C which inherits from class B which inherits from class A. Suppose class B contains objects of class E and of F. We create an object of class D. The class D constructor first calls the class C constructor which first calls the class B constructor which first calls the class A constructor. The class A constructor executes. Then the class B constructor executes. Then the class B constructor causes a constructor of class E to be called followed by a class F constructor. Then the class B constructor executes.Then the class C constructor executes. Finally the class A constructor executes. The general rule is" a class constructor can be confident that all the data it might wish to depend on ( that is, all the data that comes from inheritance and composition) has had its constructors executed already. There is a similar complication when finalize methods are used. Here, however, the nested order of calls is not automatic. Instead, each class's finalize method should start by calling the finalize method of its base class ( super.finalize( ) ). Downcasting is used when upcasting previously assigned an object of a derived class to an object variable of a base class, but we want to access a method of the derived class on this object. Suppose class A inherits from class B. We have an object of class A that we have assigned to a class B object variable. Class A implements a method, sample, that we want to apply to this object. If the object variable is named bb, we could use: (A) bb.sample( ) where the initial set of parentheses casts the object referenced by the bb object variable to being treated as an object of class A. Remember, such casts will not work when the object is not actually a member of the class to which the object variable is cast.