8.2.1 Examples of Inheritance

This section illustrates inheritance of class members through several examples.

8.2.1.1 Example: Inheritance with Default Access

Consider the example where the points package declares two compilation units:


package points;


public class Point {
	int x, y;
public void move(int dx, int dy) { x += dx; y += dy; } }

and:


package points;


public class Point3d extends Point {
	int z;
	public void move(int dx, int dy, int dz) {
		x += dx; y += dy; z += dz;
	}
}

and a third compilation unit, in another package, is:


import points.Point3d;


class Point4d extends Point3d {
	int w;
	public void move(int dx, int dy, int dz, int dw) {
		x += dx; y += dy; z += dz; w += dw; // compile-time errors
	}
}

Here both classes in the points package compile. The class Point3d inherits the fields x and y of class Point, because it is in the same package as Point. The class Point4d, which is in a different package, does not inherit the fields x and y of class Point or the field z of class Point3d, and so fails to compile.

A better way to write the third compilation unit would be:


import points.Point3d;


class Point4d extends Point3d {
	int w;
	public void move(int dx, int dy, int dz, int dw) {
		super.move(dx, dy, dz); w += dw;
	}
}

using the move method of the superclass Point3d to process dx, dy, and dz. If Point4d is written in this way it will compile without errors.

8.2.1.2 Inheritance with public and protected

Given the class Point:


package points;


public class Point {

public int x, y;

protected int useCount = 0;

static protected int totalUseCount = 0;
public void move(int dx, int dy) { x += dx; y += dy; useCount++; totalUseCount++; }
}

the public and protected fields x, y, useCount and totalUseCount are inherited in all subclasses of Point. Therefore, this test program, in another package, can be compiled successfully:


class Test extends points.Point {
	public void moveBack(int dx, int dy) {
		x -= dx; y -= dy; useCount++; totalUseCount++;
	}
}

8.2.1.3 Inheritance with private

In the example:


class Point {

int x, y;
void move(int dx, int dy) { x += dx; y += dy; totalMoves++; }

private static int totalMoves;

void printMoves() { System.out.println(totalMoves); }
}
class Point3d extends Point {
int z;
void move(int dx, int dy, int dz) { super.move(dx, dy); z += dz; totalMoves++; }
}

the class variable totalMoves can be used only within the class Point; it is not inherited by the subclass Point3d. A compile-time error occurs at the point where method move of class Point3d tries to increment totalMoves.

8.2.1.4 Accessing Members of Inaccessible Classes

Even though a class might not be declared public, instances of the class might be available at run time to code outside the package in which it is declared if it has a public superclass or superinterface. An instance of the class can be assigned to a variable of such a public type. An invocation of a public method of the object referred to by such a variable may invoke a method of the class if it implements or overrides a method of the public superclass or superinterface. (In this situation, the method is necessarily declared public, even though it is declared in a class that is not public.)

Consider the compilation unit:


package points;


public class Point {
	public int x, y;
	public void move(int dx, int dy) {
		x += dx; y += dy;
	}
}

and another compilation unit of another package:


package morePoints;


class Point3d extends points.Point {
	public int z;
	public void move(int dx, int dy, int dz) {
		super.move(dx, dy); z += dz;
	}
}

public class OnePoint { static points.Point getOne() { return new Point3d(); } }

An invocation morePoints.OnePoint.getOne() in yet a third package would return a Point3d that can be used as a Point, even though the type Point3d is not available outside the package morePoints. The method move could then be invoked for that object, which is permissible because method move of Point3d is public (as it must be, for any method that overrides a public method must itself be public, precisely so that situations such as this will work out correctly). The fields x and y of that object could also be accessed from such a third package.

While the field z of class Point3d is public, it is not possible to access this field from code outside the package morePoints, given only a reference to an instance of class Point3d in a variable p of type Point. This is because the expression p.z is not correct, as p has type Point and class Point has no field named z; also, the expression ((Point3d)p).z is not correct, because the class type Point3d cannot be referred to outside package morePoints. The declaration of the field z as public is not useless, however. If there were to be, in package morePoints, a public subclass Point4d of the class Point3d:


package morePoints;


public class Point4d extends Point3d {
	public int w;
	public void move(int dx, int dy, int dz, int dw) {
		super.move(dx, dy, dz); w += dw;
	}
}

then class Point4d would inherit the field z, which, being public, could then be accessed by code in packages other than morePoints, through variables and expressions of the public type Point4d.