Summary of Lecture for June 22, 1999 Topics: when to use inheritance and when to use composition, uses of protected and final Composition and inheritance are two techniques for reusing code. Each has advantgaes and disadvantages when compared to the other. Advantages of Composition over Inheritance: 1. The new class does not have to support the interface of the object being reused by being a data field of this class's objects. The data field can be private, protected, or package visibility and thus you can restrict where that object can be accessed. You could make the field public, if you wish any client of your new class to be able to access the composed object's interface (its methods). 2. The composed data field is an object variable and can thus be assigned new objects during the execution of the new class's objects. Using the upcasting discussed later today, the new objects can be of different derived classes of the base class that is the data field's declared type. If this is done carefully, the data field can thus be used to support different semantics ( take on different roles) at different times during execution. Advantages of Inheritance Over Composition: 1. Objects of the new class can act as if they were objects of the base class using the upcasting to be described later today. 2. Methods in the derived class can be automatically called when the user calls a method of the base class using object-oriented polymorphism as discussed tomorrow. 3. Inheritance supports incremental development. These advantages indicate which technique should be used when: 1. Composition should be used when you want to hide your use of an object of a given class from clients of your class; 2. Composition should be used when you want to take on different roles in the same object ( the parent object that contains the composed object variable) at different times during a single execution without changing your code or using conditional statements. 3. Inheritance should be used when you want to take advantage of either upcasting or polymorphism. The most common such usage is when you want the different items in an array or a collection ( to be covered July 1st) to come from different derived types of a common base class. 4. Inheritance should you be used when you want objects of the new class to implement the same interface as the base class. When should private, protected, public and package visibility modifiers be used? The general guidelines are: 1. object data items should almost never be public. 2. class data items should almost never be public. 3. object methods should be public, if they provide a service to the clients of your object. Otherwise, usually they should be protected. 4. class methods should be protected or package in most circumstances. 5. class data items should usually be package visibility and sometimes protected. 6. object data items should usually be protected visibility and sometimes package. 7. For final classes, protected above can be replaced by private. Upcasting is one of the two foundations of object-oriented programming. The other foundation, object-oriented polymorphism will be discussed tomorrow. Upcasting means that objects of a derived class can serve as if they were objects of their base class. This allows one to declare a base class object variable and assign to it an object of a derived class. Further, whenever a parameter or return value is supposed to be an object or object variable of a base class, you can use an object or object variable of the derived class instead. Note that objects of the derived class are not actually objects of the base class. In particular, derived class objects cannot access the private data and methods of base class objects. We discussed various uses of the final modifier. final generally means the modified item cannot change its value once a value has been assigned. static generally means there will be one copy of the modified item that will have storage associated with it from the moment the container ( class or object) is created until that container is no longer accessible. A variable of a primitive type can have the modifier final. This use of final indicates that variable is actually a constant. It must be assigned a value at the point of definition. If final and static are used as modifiers, the item has only one copy and that copy cannot be changed. If final is used on an object variable, the handle associated with that value cannot change, but the actual object referenced by that handle can have its data fields change value. Arrays work the same way. An array acts just like an object except it has no class. If final is used on a method, it indicates that method cannot be overridden in any inheriting class. This use of final may result in more efficient code. If final is used on a parameter in the called method's header, that parameter cannot be changed by the called method. If final is applied to a class, that class cannot serve as a base class.