• 沒有找到結果。

Extending Classes

在文檔中 Beginning Java 7Get coding with (頁 88-92)

Java provides the reserved word extends for specifying a hierarchical relationship between two classes.

For example, suppose you have a Vehicle class and want to introduce Car and Truck classes that extend Vehicle. Listing 2-21 uses extends to cement these relationships.

Listing 2-21. Relating classes via extends class Vehicle

{

// member declarations }

class Car extends Vehicle {

// member declarations }

class Truck extends Vehicle {

// Member declarations }

Listing 2-21 codifies relationships that are known as “is-a” relationships: a car or a truck is a kind of vehicle. In this relationship, Vehicle is known as the base class, parent class, or superclass; and each of Car and Truck is known as the derived class, child class, or subclass.

■ Caution You cannot extend a final

class. For example, if you declared

Vehicle

as

final class Vehicle

, the compiler would report an error upon encountering

class Car extends Vehicle

or

class Truck extends Vehicle

. Developers declare their classes

final

when they do not want these classes to be extended (for security or other reasons).

As well as being capable of providing its own member declarations, each of Car and Truck is capable of inheriting member declarations from its Vehicle superclass. As Listing 2-22 shows, non-private inherited members become accessible to members of the Car and Truck classes.

Listing 2-22. Inheriting members class Vehicle

{

private String make;

private String model;

private int year;

Vehicle(String make, String model, int year) {

this.make = make;

this.model = model;

this.year = year;

CHAPTER 2  DISCOVERING CLASSES AND OBJECTS

Car(String make, String model, int year, int numWheels) {

super(make, model, year);

this.numWheels = numWheels;

}

public static void main(String[] args) {

Car car = new Car("Toyota", "Camry", 2011, 4);

System.out.println("Make = "+car.getMake());

System.out.println("Model = "+car.getModel());

System.out.println("Year = "+car.getYear());

System.out.println("Number of wheels = "+car.numWheels);

System.out.println();

car = new Car("Aptera Motors", "Aptera 2e/2h", 2012, 3);

System.out.println("Make = "+car.getMake());

System.out.println("Model = "+car.getModel());

System.out.println("Year = "+car.getYear());

System.out.println("Number of wheels = "+car.numWheels);

} }

class Truck extends Vehicle {

private boolean isExtendedCab;

Truck(String make, String model, int year, boolean isExtendedCab) {

super(make, model, year);

this.isExtendedCab = isExtendedCab;

}

public static void main(String[] args) {

Truck truck = new Truck("Chevrolet", "Silverado", 2011, true);

System.out.println("Make = "+truck.getMake());

System.out.println("Model = "+truck.getModel());

System.out.println("Year = "+truck.getYear());

System.out.println("Extended cab = "+truck.isExtendedCab);

CHAPTER 2  DISCOVERING CLASSES AND OBJECTS

} }

Listing 2-22’s Vehicle class declares private fields that store a vehicle’s make, model, and year; a constructor that initializes these fields to passed arguments; and getter methods that retrieve these fields’ values.

The Car subclass provides a private numWheels field, a constructor that initializes a Car object’s Vehicle and Car layers, and a main() class method for testing this class. Similarly, the Truck subclass provides a private isExtendedCab field, a constructor that initializes a Truck object’s Vehicle and Truck layers, and a main() class method for testing this class.

Car’s and Truck’s constructors use reserved word super to call Vehicle’s constructor with Vehicle-oriented arguments, and then initialize Car’s numWheels and Truck’s isExtendedCab instance fields, respectively. The super() call is analogous to specifying this() to call another constructor in the same class, but invokes a superclass constructor instead.

■ Caution The super()

call can only appear in a constructor. Furthermore, it must be the first code that is specified in the constructor. If

super()

is not specified, and if the superclass does not have a noargument constructor, the compiler will report an error because the subclass constructor must call a noargument superclass constructor when

super()

is not present.

Car’s main() method creates two Car objects, initializing each object to a specific make, model, year, and number of wheels. Four System.out.println() method calls subsequently output each object’s information. Similarly, Truck’s main() method creates a single Truck object, and also initializes this object to a specific make, model, year, and flag (Boolean true/false value) indicating that the truck is an extended cab. The first three System.out.println() method calls retrieve their pieces of information by calling a Car or Truck instance’s inherited getMake(), getModel(), and getYear() methods.

The final System.out.println() method call directly accesses the instance’s numWheels or

isExtendedCab instance field. Although it’s generally not a good idea to access an instance field directly (because it violates information hiding), each of the Car and Truck class’s main() methods, which provides this access, is present only to test these classes and would not exist in a real application that uses these classes.

Assuming that Listing 2-22 is stored in a file named Vehicle.java, execute javac Vehicle.java to compile this source code into Vehicle.class, Car.class, and Truck.class classfiles. Then execute java Car to test the Car class. This execution results in the following output:

Make = Toyota Model = Camry Year = 2011

Number of wheels = 4 Make = Aptera Motors Model = Aptera 2e/2h Year = 2012

Number of wheels = 3

Continuing, execute java Truck to test the Truck class. This execution results in the following output:

CHAPTER 2  DISCOVERING CLASSES AND OBJECTS

Make = Chevrolet Model = Silverado Year = 2011

Extended cab = true

■ Note A class whose instances cannot be modified is known as an immutable class. Vehicle

is an example. If

Car

’s and

Truck

’s

main()

methods, which can directly read/write

numWheels

or

isExtendedCab

, were not present,

Car

and

Truck

would also be examples of immutable classes. Also, a class cannot inherit constructors, nor can it inherit private fields and methods. For example,

Car

does not inherit

Vehicle

’s constructor, nor does it inherit

Vehicle

’s private

make

,

model

, and

year

fields.

A subclass can override (replace) an inherited method so that the subclass’s version of the method is called instead. Listing 2-23 shows you that the overriding method must specify the same name,

parameter list, and return type as the method being overridden.

Listing 2-23. Overriding a method class Vehicle

{

private String make;

private String model;

private int year;

Vehicle(String make, String model, int year) {

this.make = make;

this.model = model;

this.year = year;

}

void describe() {

System.out.println(year+" "+make+" "+model);

} }

class Car extends Vehicle {

private int numWheels;

Car(String make, String model, int year, int numWheels) {

super(make, model, year);

}

void describe() {

System.out.print("This car is a "); // Print without newline – see Chapter 1.

super.describe();

}

public static void main(String[] args)

CHAPTER 2  DISCOVERING CLASSES AND OBJECTS

{

Car car = new Car("Ford", "Fiesta", 2009, 4);

car.describe();

} }

Listing 2-23’s Car class declares a describe() method that overrides Vehicle’s describe() method to output a car-oriented description. This method uses reserved word super to call Vehicle’s describe() method via super.describe();.

■ Note Call a superclass method from the overriding subclass method by prefixing the method’s name with

reserved word

super

and the member access operator. If you don’t do this, you end up recursively calling the subclass’s overriding method. Use

super

and the member access operator to access non-

private

superclass fields from subclasses that mask these fields by declaring same-named fields.

If you were to compile Listing 2-23 (javac Vehicle.java) and run the Car application (java Car), you would discover that Car’s overriding describe() method executes instead of Vehicle’s overridden describe() method, and outputs This car is a 2009 Ford Fiesta.

■ Caution You cannot override a final

method. For example, if

Vehicle

’s

describe()

method was declared as

final void describe()

, the compiler would report an error upon encountering an attempt to override this

method in the

Car

class. Developers declare their methods

final

when they do not want these methods to be

overridden (for security or other reasons). Also, you cannot make an overriding method less accessible than the

method it overrides. For example, if

Car

’s

describe()

method was declared as

private void describe()

, the

compiler would report an error because private access is less accessible than the default package access.

在文檔中 Beginning Java 7Get coding with (頁 88-92)