Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions

  




 

 

Thinking in Java
Prev Contents / Index Next

Inheritance syntax

Inheritance is an integral part of Java (and all OOP languages). It turns out that you’re always doing inheritance when you create a class, because unless you explicitly inherit from some other class, you implicitly inherit from Java’s standard root class Object.

The syntax for composition is obvious, but to perform inheritance there’s a distinctly different form. When you inherit, you say “This new class is like that old class.” You state this in code by giving the name of the class as usual, but before the opening brace of the class body, put the keyword extends followed by the name of the base class. When you do this, you automatically get all the fields and methods in the base class. Here’s an example:

//: c06:Detergent.java
// Inheritance syntax & properties.
import com.bruceeckel.simpletest.*;

class Cleanser {
  protected static Test monitor = new Test();
  private String s = new String("Cleanser");
  public void append(String a) { s += a; }
  public void dilute() { append(" dilute()"); }
  public void apply() { append(" apply()"); }
  public void scrub() { append(" scrub()"); }
  public String toString() { return s; }
  public static void main(String[] args) {
    Cleanser x = new Cleanser();
    x.dilute(); x.apply(); x.scrub();
    System.out.println(x);
    monitor.expect(new String[] {
      "Cleanser dilute() apply() scrub()"
    });
  }
}

public class Detergent extends Cleanser {
  // Change a method:
  public void scrub() {
    append(" Detergent.scrub()");
    super.scrub(); // Call base-class version
  }
  // Add methods to the interface:
  public void foam() { append(" foam()"); }
  // Test the new class:
  public static void main(String[] args) {
    Detergent x = new Detergent();
    x.dilute();
    x.apply();
    x.scrub();
    x.foam();
    System.out.println(x);
    System.out.println("Testing base class:");
    monitor.expect(new String[] {
      "Cleanser dilute() apply() " +
      "Detergent.scrub() scrub() foam()",
      "Testing base class:",
    });
    Cleanser.main(args);
  }
} ///:~


This demonstrates a number of features. First, in the Cleanser append( ) method, Strings are concatenated to s using the += operator, which is one of the operators (along with ‘+’) that the Java designers “overloaded” to work with Strings.

Second, both Cleanser and Detergent contain a main( ) method. You can create a main( ) for each one of your classes, and it’s often recommended to code this way so that your test code is wrapped in with the class. Even if you have a lot of classes in a program, only the main( ) for the class invoked on the command line will be called. (As long as main( ) is public, it doesn’t matter whether the class that it’s part of is public.) So in this case, when you say java Detergent, Detergent.main( ) will be called. But you can also say java Cleanser to invoke Cleanser.main( ), even though Cleanser is not a public class. This technique of putting a main( ) in each class allows easy unit testing for each class. And you don’t need to remove the main( ) when you’re finished testing; you can leave it in for later testing.

Here, you can see that Detergent.main( ) calls Cleanser.main( ) explicitly, passing it the same arguments from the command line (however, you could pass it any String array).

It’s important that all of the methods in Cleanser are public. Remember that if you leave off any access specifier, the member defaults to package access, which allows access only to package members. Thus, within this package, anyone could use those methods if there were no access specifier. Detergent would have no trouble, for example. However, if a class from some other package were to inherit from Cleanser, it could access only public members. So to plan for inheritance, as a general rule make all fields private and all methods public. (protected members also allow access by derived classes; you’ll learn about this later.) Of course, in particular cases you must make adjustments, but this is a useful guideline.

Note that Cleanser has a set of methods in its interface: append( ), dilute( ), apply( ), scrub( ), and toString( ). Because Detergent is derived from Cleanser (via the extends keyword), it automatically gets all these methods in its interface, even though you don’t see them all explicitly defined in Detergent. You can think of inheritance, then, as reusing the class.

As seen in scrub( ), it’s possible to take a method that’s been defined in the base class and modify it. In this case, you might want to call the method from the base class inside the new version. But inside scrub( ), you cannot simply call scrub( ), since that would produce a recursive call, which isn’t what you want. To solve this problem, Java has the keyword super that refers to the “superclass” that the current class has been inherited from. Thus the expression super.scrub( ) calls the base-class version of the method scrub( ).

When inheriting you’re not restricted to using the methods of the base class. You can also add new methods to the derived class exactly the way you put any method in a class: just define it. The method foam( ) is an example of this.

In Detergent.main( ) you can see that for a Detergent object, you can call all the methods that are available in Cleanser as well as in Detergent (i.e., foam( )).
Thinking in Java
Prev Contents / Index Next


 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire