LECTURE NOTES CHAPTER 13 INHERITANCE - goals: - code reuse - enhance existing classes - new class can inherit from existing class representing more general concept - superclass - more general class - basis for inheritance - subclass - more specialized class - inherits from superclass e.g. - a Student is a more specialized kind of LifeForm - a subclass can have only one superclass - a superclass can have many subclasses - syntax: defining a class that inherits from another class extends {...} e.g. public class Student extends LifeForm {} - defining subclass - automatically inherits all methods and instance fields - specify - additional instance fields - changed/overridden methods - additional methods e.g. LifeForm - instance fields: age, size, energy - methods: consume, grow, reproduce Student - instance fields: happiness - methods: study, drinkBeer - methods of a subclass cannot access private fields of the superclass, even though subclass object still has those fields e.g. implement Student::study - want it to decrease happiness and energy - as is, can't change energy directly! - add: changeEnergy to LifeForm - within a subclass method, method calls without an implicit parameter refer to the object that called the original method e.g. implement Student::study - changeEnergy(-1) same as this.changeEnergy(-1) - because the method is inherited, all Student objects can call it - every class that does not specifically extend another class is a subclass of Object - means all objects support Object methods such as toString - UML - solid arrow with triangle tip - points to superclass e.g. diagram LifeForm's relationship to Student - subclass object diagram - show inherited instance fields separately - object type is subclass e.g. diagram Student object - difference from implementing interface - interface has no state and no behavior - superclass has both, and subclasses inherit them INHERITANCE HIERARCHIES - represent as tree - most general concept at root - more specialized concepts toward branches - inheritance hierarchy - common way of grouping Java classes - most general class at root - more specialized classes toward branches e.g. Home, House, Apartment, Efficiency, OneBedroom, TwoBedroom - designing class hierarchy - determine universally common features and behaviors: superclass e.g. LifeForm - subclasses - support all methods from the superclass - implementations may be modified to match their specialized purposes - free to introduce additional methods e.g. Student INHERITING INSTANCE FIELDS AND METHODS - specify additional instance fields and methods of a subclass - defining methods - inherit methods - automatically if superclass method not overrided - can be applied to the subclass objects - define new methods - can only be applied to subclass objects - override methods from the superclass - specify method with same signature - overrided method, not original one, is executed e.g. want Student's reproduce method to increase happiness - overriding vs. overloading vs. interface polymorphics - same method name - overloading - within same class - different numbers or types of parameters - early binding - polymorphism - among different classes - late binding - interface - interface declares method - choose among the classes that implement it - overriding - subclass and superclass declare and implement method - choose between these two - defining instance fields - can never override - subclass automatically inherits all superclass fields - define new fields: present only in subclass - define a new field with the same name as the superclass field - legal - each object would have two fields with the same name - the fields can hold different values - called shadowing - very bad style e.g. add energy instance field to Student - specify invocation of superclass method - keyword super - use like "this", only refers to inherited aspects of the object - useful when overriding method use overridden method functionality - by default, will refer to subclass method by that name e.g. Student::reproduce() SUBCLASS CONSTRUCTION e.g. LifeForm() calls LifeForm(int, int, int) - invoke the superclass constructor - syntax: super(); - must be the first statement of the subclass constructor e.g. Student() - if superclass constructor not called explicitly - implicitly called on default constructor - can get compiler error if all superclass constructors require parameters - subclass constructors commonly have parameters - some passed on to superclass constructor - some used to initialize subclass fields e.g. Student(int, int, int, int) CONVERTING BETWEEN SUBCLASS AND SUPERCLASS TYPES - convert a subclass to a superclass type - when a subclass extends a superclass, a subclass object is a special case of a superclass object - reference to subclass object can be converted to superclass reference e.g. LifeForm lf = new Student(); - all references can be converted to type Object e.g. Object o = lf; - multiple reference variables of different types may point to the same object e.g. draw results of above two statements - can only use methods of the type of the reference variable, even if the object is a subclass and has additional methods - motivation: reuse code that knows about the superclass but not the subclass - can use a subclass reference wherever a superclass is expected e.g. o.toString(); + lf.toString(); + o.reproduce(); x lf.reproduce(); + o.drinkBeer(); x lf.drinkBeer(); x - convert from a superclass reference to a subclass reference - rare - use a cast - if wrong at runtime, causes an exception e.g. Student s = (Student) o; - instanceof operator - test whether an object belongs to a particular type - syntax: instanceof - returns true if is convertible to - could be - could be subclass of - use to make casts safe by making their execution dependent on instanceof e.g. if (o instanceof Student) { Student s = (Student) o; } POLYMORPHISM - type of a variable doesn't completely depend on type of object to which it refers - variable with a given class as it's type can hold objects of that class or subclasses of that class - similar to interface variables - which method is called - always determined by the type of the actual object - not the type of the object reference - polymorphism: ability to refer to objects of multiple types with varying behavior - use more specific types for variables so compiler can check that only legal methods are invoked - method calls made without an explicit object - use the implicit parameter, this - what code is executed can still vary - this could refer to an object of the current class or a subclass e.g. class PolySuper, class PolySub output: a1 a2 a1 b2 a1 b2 OBJECT: THE COSMIC SUPERCLASS - every class defined without an explicit extends clause automatically extends the class Object - Object is the direct or indirect superclass of every class in Java e.g. complete Student hierarchy - useful Object methods - String toString() - returns a string representation of the object - boolean equals(Object otherObject) - tests whether the object equals another object - Object clone() - makes a full copy of an object - good idea to override these in your classes OVERRIDING THE TOSTRING METHOD - returns a string represenation for each object - should describe the object state - called whenever you concatenate a string with an object - whenever one argument to the + operator is a string - compiler automatically invokes the toString method of the other to convert it to a string too - then concatentates the two strings - works because compiler knows every object has a toString method, because Object does, and every class inherits from Object - this process is different for primitives - they don't have any methods, much less the toString one - Object implementation - class name followed by the hash code - hash code used to tell objects apart: different objects likely to have different hash codes - better to override the object to expose state - recommended format - first print name of class - then values of the instance fields inside brackets e.g. LifeForm::toString() public toString() { String stringRep = "LifeForm[age=" + age + ", size=" + size; stringRep += ", energy=" + energy + "]"; return stringRep; } - useful for debugging - simply print the object - println automatically calls toString to convert its argument to a string first INHERITANCE AND THE TOSTRING METHOD - make toString method useable by subclasses - class Class - describes classes and their properties - @return the name of the class String getName() - Class Object::getClass method @return the dynamic class of the object - in superclass - use getClass.getName() instead of hard-coding class name e.g. LifeForm::toString() - in subclass - override toString - add values of the subclass instance fields - call super.toString() to get superclass field values - use brackets to show which fields belong to the superclass e.g. Student::toString()