The Solution: Interfaces

   

Java™ 2 Primer Plus
By Steven Haines, Steve Potts

Table of Contents
Chapter 7.  Inheritance


Aside from being a fun exercise, designing our dream Porsche and completely ripping apart any integrity that the Pinto might have had, you might have noticed a lot of similarities between the Porsche class and the Pinto class. Yes, all the performance metrics are different, but each shares similar attributes and methods. The common attributes are

  • horsePower

  • maximumSpeed

  • numberOfDoors

  • paint

  • gasCapacity

  • oilCapacity

  • transmission

  • running

  • currentSpeed

  • currentGas

  • currentOil

And the following methods are common:

  • start

  • stop

  • accelerate

  • decelerate

  • isRunning

  • getCurrentSpeed

What happens when we want to create a Corvette class? Or an Accord class? Do we have to duplicate all this common functionality in all the car classes that we build?

The answer is no, and the object-oriented concept that will help us is called inheritance. The idea is that you can group all the common functionality into a class called Car; create specializations of that Car that inherit all that common functionality; and then add all the special features that make it unique. For example, you can create a Porsche from a Car.

Listing 7.3 shows the code for the Car class.

Listing 7.3 Car.java
 public class Car   {      // Transmission types      public static final int AUTOMATIC = 0;      public static final int TIPTRONIC = 1;      public static final int MANUAL = 2;      // Attributes      protected String typeOfCar;      protected int horsePower;      protected int maximumSpeed;      protected int numberOfDoors;      protected String paint;      protected int gasCapacity;      protected int oilCapacity;      protected int transmission;      // State attributes      protected boolean running = false;      protected int currentSpeed;      protected int currentGas;      protected int currentOil;      public Car( String typeOfCar,                  int horsePower,                  int maximumSpeed,                   int numberOfDoors,                   String paint,                  int gasCapacity,                  int oilCapacity,                  int transmission )      {          this.typeOfCar = typeOfCar;          this.horsePower = horsePower;          this.maximumSpeed = maximumSpeed;          this.numberOfDoors = numberOfDoors;          this.paint = paint;          this.gasCapacity = gasCapacity;          this.oilCapacity = oilCapacity;          this.transmission = transmission;      }      public void start()      {          running = true;      }      public void stop()      {          running = false;      }      public boolean isRunning()      {          return running;      }      public void accelerate()      {          currentSpeed += 5;      }      public void decelerate()      {          currentSpeed -= 5;      }      public int getCurrentSpeed()      {          return currentSpeed;      }      public String toString()      {          return typeOfCar;      }  } 

The Car class contains all the common functionality that we found between the Porsche, the Pinto, and other cars that we might want to build in the future. It provides default implementation for starting and stopping the car, returning the current speed, checking whether it is running, and accelerating and decelerating the car. One change that you will notice to the attributes in the Car class is that now instead of being private, they have a new access modifier called protected. The protected access modifier offers the same level of protection that private offers to classes outside of the Car class, but enables them to be publicly accessible by all new classes that specialize the Car class (more on that in a minute).

The acceleration and deceleration implementations differ dramatically between the cars, but we'll address that in a minute. The next order of business is to create a Porsche and a Pinto from the car we just created. The process of creating a new class from an existing class is called extending; the new class extends the old class. Java facilitates this through the keyword: extends.

Listing 7.4 shows the new code for the Porsche2 class that extends the Car class.

Listing 7.4 Porsche2.java
 public class Porsche2 extends Car  {      // Attributes      private int turbos = 2;      private boolean nos;      // State attributes      private boolean turbo1Engaged = false;      private boolean turbo2Engaged = false;      private boolean nosEnabled = false;      public Porsche2()      {          super( "Porsche",                 450,                 220,                 2,                 "Yellow",                 15,                 5,                 Car.TIPTRONIC );      }      public void accelerate()      {          // Check to see if we are running or not          if( running == false )          {              return;          }          // Create a variable representing how much we are going to           // accelerate this second          int increment = 15;          // Check the turbos; they add 5mph per second acceleration          if( turbo1Engaged )          {              increment += 5;          }          if( turbo2Engaged )          {              increment += 5;          }          // Check the NOS; it represents 15mph per second          if( nos )          {              increment += 15;           }          // Increment the current speed          currentSpeed += increment;          if( currentSpeed > maximumSpeed ) currentSpeed = maximumSpeed;      }      public void decelerate()      {          currentSpeed -= 20;          if( currentSpeed < 0 ) currentSpeed = 0;      }      public void engageTurbos()      {          turbo1Engaged = true;          turbo2Engaged = true;      }      public void disengageTurbos()      {          turbo1Engaged = false;          turbo2Engaged = false;      }      public void engageNOS()      {          nos = true;          maximumSpeed += 50;      }      public void disengageNOS()      {          nos = false;          maximumSpeed -= 50;       }      public String toString()      {          return "A shiny new " + paint + " Porsche!";       }      public static void main( String[] args )      {          Porsche2 p = new Porsche2();          System.out.println( "My new car: " + p );          p.start();          System.out.println( "Current speed: " + p.getCurrentSpeed() );          for( int i=0; i<20; i++ )          {              if( i == 5 )              {                  p.engageTurbos();              }              else if( i == 14 )              {                  p.engageNOS();              }              p.accelerate();              System.out.println( "Current speed: " + p.getCurrentSpeed() );          }          p.disengageNOS();          p.disengageTurbos();          while( p.getCurrentSpeed() > 0 )           {              p.decelerate();              System.out.println( "Current speed: " + p.getCurrentSpeed() );          }          p.stop();      }  } 

Listing 7.4 requires some discussion. The Porsche2 extends the Car class using the extends keyword in the following line:

 public class Porsche2 extends Car 

Next it defines the attributes that are specific to a Porsche: its turbo and Nitrous Oxide System.

The constructor does something interesting; its first line is a call to the super method. The Car class, in this example, is referred to as the super class, or base class, and the Porsche2 is referred to as the subclass, or derived class. This relationship denotes that the Porsche2 class inherits all the functionality from the Car class, not vice versa. Because the relationship is super class to subclass, subclasses have a variable in them similar to the this variable called the super variable. Although the this variable refers to this instance of a class, the super variable refers to the instance of the super class. Similar to the way you can reference a class's own methods and variables by prefacing the method or variable with this. You can reference the super class's methods and variables by prefacing the method or variable with super.

Along with the super variable, there is also a super method that is used to invoke one of the super class's constructors. The way that the Java Runtime Engine handles the creation of classes with inheritance is by following these steps:

  1. Create the class

  2. Initialize all the super class's class variables

  3. Initialize all the subclass's class variables

  4. Execute the super class's constructor

  5. Execute the subclass's constructor

The super method is the way that your subclass can decide which of the super class's constructors will be executed. The constraint is that because the super class's constructor is executed before the subclass's constructor, the super method, if used, must be the first statement in the subclass's constructor. If no super method is provided in the subclass's constructor, the default constructor is used. Recall that the default constructor is one that does not accept any parameters. If there is not a default constructor in the super class, you must specify which constructor to execute by using the super method.

The Porsche2 class's constructor calls the only constructor defined in the car class using the super method:

 super( "Porsche",         450,         220,         2,         "Yellow",         15,         5,         Car.TIPTRONIC ); 

This passes the relevant data to the Car class to initialize its variables.

The Porsche2 class then overloads the accelerate and decelerate methods. The term overloading means that the subclass provides a method with the exact same signature as a method in the super class, and it is executed instead of the super class's method. In this case, the Porsche2 class's accelerate method is executed instead of the Car class's accelerate method. This is a powerful concept because the Car class can provide a default implementation, but any of the subclasses are free to overload it and provide a custom implementation. The implementations of the accelerate and decelerate methods are the same as the ones from the original Porsche class.

The rest of the class implements the custom Porsche2 methods.

Listing 7.5 shows the updated Pinto class: Pinto2.

Listing 7.5 Pinto2.java
 public class Pinto2 extends Car  {      // State attributes      public boolean hatchBackDoorOpen = false;      public Pinto2()      {          super( "Pinto",                 50,                 60,                 5,                 "two-tone",                 15,                 5,                 Car.MANUAL );      }      public void accelerate()      {          // Check to see if we are running or not          if( running == false )          {              return;          }          currentSpeed += 4;          if( currentSpeed > maximumSpeed )          {              currentSpeed = maximumSpeed;              // The high speed knocked the door open!              openHatchBack();          }      }      public void decelerate()      {          currentSpeed -= 5;          if( currentSpeed < 0 ) currentSpeed = 0;      }      public void rollStart()      {          running = true;      }      public void pushUpHill()      {          System.out.println( "Ouch, this thing is heavy!" );      }      public void openHatchBack()       {          hatchBackDoorOpen = true;      }      public void closeHatchBack()      {          hatchBackDoorOpen = false;      }      public boolean isHatchBackDoorOpen()      {          return hatchBackDoorOpen;      }      public static void main( String[] args )      {          Pinto2 p = new Pinto2();          System.out.println( "My car: " + p );          p.start();          if( p.isRunning() == false )          {              System.out.println( "Starter failed, let's roll start it!" );              p.rollStart();          }          System.out.println( "Current speed: " + p.getCurrentSpeed() +                              ", Hatchback open = " + p.isHatchBackDoorOpen() );          for( int i=0; i<20; i++ )          {              p.accelerate();              System.out.println( "Current speed: " + p.getCurrentSpeed() +                                  ", Hatchback open = " + p.isHatchBackDoorOpen() );          }          while( p.getCurrentSpeed() > 0 )          {              p.decelerate();              System.out.println( "Current speed: " + p.getCurrentSpeed() +                                  ", Hatchback open = " + p.isHatchBackDoorOpen() );          }          p.stop();          if( p.isHatchBackDoorOpen() )          {              System.out.println( "Have to close the hatchback!" );              p.closeHatchBack();          }      }  } 

The Pinto2 class is very similar to the Porsche2 class in that it extends the Car class, calls the similar Car class constructor using the super method, overrides the accelerate and decelerate methods, and provides its own custom methods.

The inheritance relationship is sometimes referred to as the is-a relationship because a Porsche is-a car and a Pinto is-a car.


       
    Top
     



    Java 2 Primer Plus
    Java 2 Primer Plus
    ISBN: 0672324156
    EAN: 2147483647
    Year: 2001
    Pages: 332

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