Google
 

 

up previous next contents
Up: 2. Day 2: The Previous: 2.9 Methods and parameters Next: 2.11 Interfaces   Contents

Subsections

2.10 Extending Classes

2.10.1 Introduction

  • It is easy for one Java class to extend the behavior of another Java class.
  • This capability is usually referred to as polymorphism, which means that an object of a given class can have multiple forms.

2.10.2 Objectives

  • Upon completion of this section, students will be able to:
  • Extend existing classes.
  • Define the terms subclass, superclass, overloading, and overriding.
  • Define how constructors of subclasses operate.
  • Define the implications of marking a class or method as final.
  • Discuss the considerations of cloning classes.

2.10.3 An extended class

  • An extended class can be used wherever the original class was legal.
  • Polymorphism - an object of a given class can have multiple forms.
  • The extended class is a subclass.
  • The class it extends is the superclass.
  • If a class does not explicitly extend a class then it implicitly extends Object.
  • Object declares methods that are implemented by all objects.

2.10.4 A simple example

  • A simple example of extending a base Animal class:
    public abstract class Animal
    {
      protected boolean hasColdNose;
    
      public abstract String speak();
    
      public void setHasWetNose(boolean hasColdNose) {
        this.hasColdNose = hasColdNose;
      }
      public boolean hasColdNose() {
        return hasColdNose;
      }
    }
    
    public class Dog extends Animal
    {
      public Dog() {
        hasColdNose = true;
      }
      public String speak() {
        return "woof";
      }
    }
    
    public class Bird extends Animal
    {
      public Bird() {
        hasColdNose = false;
      }
      public String speak() {
        return "chirp";
      }
    }
    

    public class Main
    {
      public Main() {
        Animal fido = new Dog();
        Animal bigbird = new Bird();
        System.out.println( "fido says " + fido.speak() );
        System.out.println( "bigbird says " + bigbird.speak() );
      }
    
      public static void main(String[] args) {
        new Main();
      }
    }
    

2.10.5 What protected really means

  • A protected class member can be accessed by classes that extend that class.
  • A protected class member also be accessed from code within the same package.
  • A protected class member also be accessed from references of the class's type or one of it's subtypes.

2.10.6 Constructors in extended classes

  • When you extend a class, the new class must choose one of it's superclass's constructors to invoke.
  • If you do not invoke a superclass constructor as your constructors first executable statement, the superclass no-arg constructor is automatically invoked before any statements in your new constructor are executed.
  • If the superclass does not have a no-arg constructor, you must explicitly invoke one of the superclass's other constructors, or invoke another of your own constructors using the this construct.
  • If you use super(), it must be the first executable statement of the constructor.
  • The language provides a default no-arg constructor for you.

2.10.6.1 Constructor order dependencies

  • When an object is created, all it's fields are set to default initial values.
  • Then the constructor is invoked.

2.10.6.2 Constructor phases

  • Invoke a superclass's constructor.
  • Initialize the fields using their initializers and any initialization blocks.
  • Execute the body of the constructor.

2.10.6.3 Constructor phase example

  • An example of how parent/child constructors work:
    public class ParentClass {
      public ParentClass() {
        System.out.println( "ParentClass constructor was called" );
      }
    }
    public class ChildClass extends ParentClass {
      public ChildClass() {
        System.out.println( "ChildClass constructor was called" );
      }
    }
    public class Main {
      public static void main(String[] args) {
        ChildClass cc = new ChildClass();
      }
    }
    

2.10.7 Overriding methods, hiding fields, and nested classes

Overloading - providing more than one method with the same name but with different signatures. Overriding - replacing a superclass's implementation with your own.

2.10.7.1 Overriding

  • Signatures must be identical.
  • Return type must be the same.
  • Only accessible non-static methods can be overridden.
  • A subclass can determine whether a parameter in an overridden method is final.

2.10.7.2 The super keyword

  • Available in all non-static methods of a class.

super.method() - uses the superclass's implementation of method.

2.10.8 Marking methods and classes final

  • No extended class can override the method to change its behavior. (This is the final version of that method.)
  • A class marked final cannot be extended by any other class (and, all the methods of a final class are implicitly final).
  • Security - anyone who uses the class can be sure the behavior will not change (validatePassword example).
  • Serious restriction on the use of the class.
  • Final simplifies optimizations.

2.10.9 The object class

  • All classes inherit from Object.
  • Object's methods fall in two classes: utilities, and thread support.

2.10.9.1 Object's utility methods

  • equals(Object o)
  • hashCode()
  • clone()
  • getClass()
  • finalize()

2.10.10 Anonymous classes

  • Use these when the weight of a full class seems too much for your needs.
  • Extend a class or implement an interface.
  • Defined at the same time they are created with new.
  • Defined in the new expression.
  • Cannot have their own constructors.
  • Can easily become hard to read.
  • Avoid anonymous classes longer than six lines.
  • Use them only in the simplest of expressions.

2.10.11 Abstract Classes and methods

  • Helpful when some of the behavior is defined for most objects of a given type, but some behavior makes sense for only particular classes and not the superclass.
  • Declare classes that define only part of an implementation.
  • Each method not implemented in an abstract class is marked abstract.
  • A class with any abstract methods must be declared abstract.
  • Abstract methods must be implemented by subclasses that are not abstract themselves.

2.10.12 Cloning objects

  • A clone method returns a new object whose initial state is a copy of the current state of the object on which clone was invoked.
  • Subsequent changes to the clone will not affect the state of the original.
  • Object.clone()

2.10.12.1 Three major considerations in writing a clone method

  • Empty Cloneable interface.
  • Object.clone() method.
  • CloneNotSupportedException.

2.10.12.2 Four different attitudes a class can have towards clone

  • Support clone.
  • Conditionally support clone.
  • Allow subclasses to support clone but don't publicly support it.
  • Forbid clone.

2.10.13 Extending classes: how and when

  • Ability to extend classes - large part of the benefits of OOP.
  • Creates an "IsA" relationship, not a "HasA" relationship.
  • Employee / Role example (see text).

2.10.14 Designing a class to be extended

  • Choose the access for each part of a class design carefully: public, protected, private.
  • If your design will have subclasses, design your protected parts carefully.

2.10.14.1 Bad effects of public fields

  • Fields can be modified at any time by a programmer.
  • No way to add functionality.

2.10.14.2 Non-final classes have two interfaces

  • Public interface for programmers using the class.
  • Protected interface for programmers extending the class.