Inheritance


We briefly touched on the concept of inheritance in the "Constructors" section earlier in this chapter. It is a powerful object-oriented capability that allows you to write one class that extends the capabilities of another. A subclass has access to the nonprivate members of its superclass. Inheritance facilitates code reuse and allows the creation of class hierarchies.

Inheritance is indicated by the extends keyword followed by the name of the superclass in a class declaration statement. A subclass can only inherit from one superclass. Unlike C++, Java does not support multiple inheritance. The general syntax for a subclass is shown below.

 [modifiers] class <class_name> extends superclass               [implements interface1, interface2, ...] {    //  field declarations    //  constructor declarations    //  method declarations    //  other declarations } 

When you create an instance of a subclass, the fields defined in both the subclass and superclasses must be initialized. The superclass fields can be initialized by having the subclass constructor first invoke a superclass constructor using the super keyword. While the subclass inherits the nonprivate methods and constructors of the superclass, it can overload or override them as it sees fit. Details on method overloading and overriding are provided in Chapter 9.

You will work with inheritance whether you want to or not. Every Java class implicitly inherits from the Object class, meaning that the Object class is the superclass (or ancestor ) of all other classes. The inheritance from Object is implicit, meaning that you don't have to write extends Object in your class declaration syntax. What this implicit inheritance from Object also means is that every class you write will have access to the methods defined in the Object class.

Example: Inheritance Basics

In this example, we will demonstrate some of the basic concepts of inheritance. We first define a class named Species that represents a simplified model of a chemical species. The fields declared by the Species class represent the species name and its molar mass. Two methods are defined to access the current value of the fields.

 public class Species {   private String name;   private double molarMass;   public Species(String nm, double mw) {     name = nm;     molarMass = mw;   }   public String getName() {     return name;   }   public double getMolarMass() {     return molarMass;   } } 

We next write a simple driver program for the Species class. The driver creates a Species object and calls the getName() and getMolarMass() methods on the object.

 public class SpeciesDriver {   public static void main(String args[]) {     Species o2 =            new Species("diatomic oxygen", 0.0319988);     System.out.println("Molar mass of " +            o2.getName() + " is " + o2.getMolarMass());   } } 

Output ”

 Molar mass of diatomic oxygen is 0.0319988 

Now, let's say we want to model an ionized species. To perform calculations with our ionized species class we might need to know the ionization level (O+, O++, etc.). Our ionized species class will have to include an ionization level as a variable. We could write a separate IonizedSpecies class, but it would have many of the same features as our Species class. Code duplication is poor object-oriented programming practice and is time-consuming as well. Instead, we will use inheritance to write a subclass of Species .

The IonizedSpecies class is written as a subclass of Species . It defines a constructor that takes three arguments. The first two are used to initialize the superclass fields defined in the Species class. Since every class is responsible for initializing its own fields, the Species class constructor is called using the super keyword. This operation must be performed first. After the Species class constructor is called, the chargeLevel variable is initialized. The IonizedSpecies class also declares an instance method that returns the value of the chargeLevel field.

 public class IonizedSpecies extends Species {   private int chargeLevel;   public IonizedSpecies(String nm, double mw,                                     int charge) {     super(nm, mw);     chargeLevel = charge;   }   public int getChargeLevel() {     return chargeLevel;   } } 

Next, we'll write a new driver program that will create and manipulate an IonizedSpecies object. In addition to the getChargeLevel() method defined in its own class, the IonizedSpecies object can also access the getName() and getMolarMass() methods from the Species class.

 public class SpeciesDriver2 {   public static void main(String args[]) {     IonizedSpecies o2p = new IonizedSpecies(                 "diatomic oxygen ion", 0.03199825, 1);     System.out.println("molar mass of " +         o2p.getName() + " is " + o2p.getMolarMass());     System.out.println("charge level of " +         o2p.getName() + " is " + o2p.getChargeLevel());   } } 

Output ”

 molar mass of diatomic oxygen ion is 0.03199825 charge level of diatomic oxygen ion is 1 

Inheritance and Access Modifiers

Inheritance is governed by the access modifiers applied to the superclass members. If you do not want a subclass to access a superclass member, give that member private access. A member that has public access is freely accessible inside or outside of the class in which it is defined. The protected access is more restrictive than public . Outside of the package in which it is defined, a protected member is only available to subclasses. If no access is specified for a member it will have public access inside its package and private access outside its package.

Table 7.1 summarizes the access types.

Inheritance and Method Arguments

When one class inherits from another, it becomes part of a class hierarchy. This has implications when passing reference type variables to methods. When a method defines a reference type as one of its input parameters, it is perfectly acceptable to pass a subclass of the specified type as an argument to the method. For example, the setListData() method from the JList class takes a Vector as an argument. You can call this method with a Stack variable as an argument because Stack is a subclass of Vector .

Example: Sending a Subclass Object to a Method

The MethodArgDemo class defines a method named capName() that takes a Species object as an input parameter. Any Species subclass object can also be passed to the method. In the main() method, an IonizedSpecies object is created and sent to the capName() method.

 public class MethodArgDemo {   //  This method takes a Species argument   public void capName(Species spc) {     System.out.println("Name is " +             spc.getName().toUpperCase());   }   public static void main(String args[]) {     MethodArgDemo demo = new MethodArgDemo();     IonizedSpecies o2p = new IonizedSpecies(                 "diatomic oxygen ion", 0.03199825, 1);     //  Call the capName() method passing it an     //  IonizedSpecies argument     demo.capName(o2p);   } } 

Output ”

 Name is DIATOMIC OXYGEN ION 

Member Hiding and Member Overriding

If a subclass defines a field with the same name as one defined by a superclass, the subclass field will hide its superclass counterpart . The subclass can access the hidden superclass field using the super keyword. If a subclass defines a method with the same return type, name, and parameter list as a superclass, the subclass method is said to override the superclass method. A subclass object that calls the method will invoke the subclass version of it. The superclass method can be invoked inside a subclass using the super keyword. Method overriding is covered in more detail in Chapter 9.



Technical Java. Applications for Science and Engineering
Technical Java: Applications for Science and Engineering
ISBN: 0131018159
EAN: 2147483647
Year: 2003
Pages: 281
Authors: Grant Palmer

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net