Section 9.3. Abstract Classes and Abstract Methods

   

9.3 Abstract Classes and Abstract Methods

There are many occasions when the following situation presents itself: You would like to define a class that can be subclassed, but allowing direct instantiation of the class would not make sense. This generally happens when you've got some behavior that you'd like to make common, but you don't have enough data for the class to be instantiated itself. Enter abstract classes.

9.3.1 Abstract Classes and Methods

An abstract class cannot be instantiated. It can define methods that subclasses will use. But you can't make an object of it. Things that are abstract are the opposite of concrete things (if you believe in opposites). What is abstract is not yet made, but it exists on a conceptual level in order to be made apparent. What is concrete exists already and is usable. Concrete classes have methods that are concrete. That is, they define exactly what they are supposed to do, and then they do that same thing in every single case.

With abstract classes, on the other hand, the idea is defined, but the implementation is not defined. The implementation must come from other classes that extend the abstract class. The usefulness of abstract classes is apparent when you need to define certain behavior for objects of a certain type, but you have specific behavior for different subclasses that you want to implement.

Note

If what you want to do is define methods without providing any implementation of them, you should really write an interface, as described above.


The way to ensure that your subclasses indeed override the methods you want is by defining them as abstract.

Abstract methods do not have a body. They have a return type, and they have parameters ”just no body. Any class containing even one abstract method must itself be declared abstract . Any subclasses then must also be abstract, unless they implement every abstract method of the superclass.

Note

You cannot declare constructors or static methods abstract.


Abstract methods are useful when the required behavior of a method is defined, but the implementation is not. Abstract methods give you the flexibility to leave the implementation up to subclasses. Consider the ubiquitous Vehicle example. That might be a case where you would define an abstract Vehicle with an abstract makeSound() method. Your Car class could then implement it with a honk, and a Bicycle class could implement it with one of those cute little metal ringers. An Animal class could work the same way: A Cat subclass could implement makeSound() to generate meows, and the Dog subclass would implement it to make barks.

Note

As long as a class does not define abstract methods, its subclasses can be either abstract or concrete. If a class defines abstract methods, they must have a concrete implementation in a subclass.


You cannot create objects of a class that contains even one abstract method. That's because a class that contains even one abstract method must itself be declared abstract . Abstract classes by definition are not complete, and they must be implemented in a subclass. You create objects of the subclass type.

Note

If a class defines even one abstract method, the entire class must be declared abstract . You may define concrete methods in an abstract class, however, and subclasses can use them directly.


Let's look at a simple example of this. Here we will make an abstract class called Vehicle , which will define certain kinds of properties and behaviors appropriate to vehicles, such as currentSpeed . The setSpeed() method will be concrete, and it will just accept a double value. We will then create two subclasses of Vehicle : Car and SpeedBoat . These subclasses provide different implementations of the getSpeed() method. The reason for this is that the speed of cars in measured in miles per hour in some places and kilometers per hour in others. For now, our cars can only drive in the United States and England. The value passed into getSpeed() will be calculated differently depending on where the car is.

9.3.2 Vehicle.java

 package javaforcf.chp9;  /* Vehicle demos the use of abstract method  * and inheritance */ abstract class Vehicle {   protected double currentSpeed;   protected String locale = "";   protected String measurement = "";   // default constructor   Vehicle() {   }   // concrete method   // doesn't get overridden here     public String drive() {       String s = "Now driving";       return s;     }   // abstract method   // notice that declaring abstract method   // disallows use of {}   public abstract double getSpeed(); } 

9.3.3 Car.java

 package javaforcf.chp9;  public class Car extends Vehicle {       // constructor overload         Car() {           super();           currentSpeed = 0.0;           locale = "US";         }       public void setSpeed(double d) {         this.currentSpeed = d;       }       public double getSpeed() {         double s = this.currentSpeed;         if (this.getMeasurement() == "MPH") return s;             // convert to kilometers         return s = s * 0.6;       }       public String getMeasurement() {         if (this.locale != "US") return "KPH";         return "MPH";       }       public String getLocale() {         return locale;       }     public static void main(String[] args) {       // create an object of the subclass       Car myCar = new Car();       System.out.println(myCar.drive() + " in " + myCar.getLocale());       myCar.setSpeed(100.0);       System.out.println("Current speed: " +             myCar.getSpeed() +  " " +             myCar.getMeasurement());     } } 

The example is a bit contrived, but it illustrates certain things. The output of compiling and running Car with "England" as the value of the locale variable produces this:

 Now driving in England  Current speed: 60.0 KPH 

Using "US" as the locale produces this output:

 Now driving in US  Current speed: 100.0 MPH 

We can also extend the Vehicle class further to demonstrate the usefulness of having the getSpeed() method declared abstract . The speed of boats is measured in knots, not in miles or kilometers. So we can pass it a value in MPH and it will convert it to knots and tell us so, acting in a way appropriate to boats:

9.3.4 SpeedBoat.java

 package javaforcf.chp9;  public class SpeedBoat extends Vehicle {       // constructor overload         SpeedBoat() {         // call superclass           super();           currentSpeed = 0.0;           locale = "water";         }       public void setSpeed(double d) {         this.currentSpeed = d;       }      public double getSpeed() {         double s = this.currentSpeed;           // do conversion for nautical miles         return s = s * 1.1507794;       }   public static void main(String[] args) {     SpeedBoat myBoat = new SpeedBoat();     System.out.println(myBoat.drive() + " in " + myBoat.getLocale());       myBoat.setSpeed(100.0);       System.out.println("Current speed: " +             myBoat.getSpeed() +  " knots");   } } 

Running SpeedBoat produces this output:

 Now driving in water  Current speed: 115.07794 knots 

We could, of course, have declared Boat a subclass of Vehicle , and extended SpeedBoat and Yacht instead. Then Yacht would have to declare properties such as SizeOfBar and NumberOfTrophies , and methods such as getGuestList() .


   
Top


Java for ColdFusion Developers
Java for ColdFusion Developers
ISBN: 0130461806
EAN: 2147483647
Year: 2005
Pages: 206
Authors: Eben Hewitt

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