This section illustrates inheritance of class members through several examples.
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; } }
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.
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++; } }
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.
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
.