ITEEDU

Java Gossip: 扩充(extends)父类别

假设您先前已经撰写了一些2D绘图相关类别,现在您想要将之扩充为适用于3D绘图,3D的观念是2D的延伸,许多 2D绘图时所使用的功能都可以留下来加以扩充,在Java中您不用重写所有的类别,您可以「扩充」(extend)原先已定义好的类别,增加新的定义。

Java中使用"extends"作为其扩充父类别的关键词,其实就相当于我们一般所常称的继承(Inherit),只不过"extends"除了继承之外,还有将继承下来的类别予以新增定义的意思。

例如绘图中最基本的「点」类别,您原先已定义好一个Point2D类别,您继承它并将之扩充为Point3D类别,在扩充的关系中,称被扩充的类别为「父类别」(Parent class)或「基础类别」(Base class),而扩充父类别的类别就称之为「子类别」(Child class)或「衍生类别」(Derived class),在扩充时您使用"extends" 关键词,并指定要被扩充的类别。

直接使用一个实际例子来说明好了:

Point2D.java
public class Point2D {
	private int x, y;
	public Point2D() {}
	public Point2D(int x, int y) {this.x = x; this.y = y;}
	public int getX() {return x;}
	public int getY() {return y;}
}
Point3D.java
public class Point3D extends Point2D { // 扩充Point2D类别
	private int z;?// 新增私用资料
	public Point3D() {
		super();
	}
	// 建构函式,同时指定呼叫父类别建构函式
	Point3D(int x, int y, int z) {
		super(x, y);
		this.z = z;
	}
	// 新增函式
	public int getZ() {return z;}
}
UseExtend.java
public class UseExtend {
	public static void main(String[] args) {
		Point3D p1 = new Point3D(1, 3, 4);
		Point3D p2 = new Point3D();
		System.out.printf("p1: (%d, %d, %d) \n",
		p1.getX(), p1.getY(), p1.getZ());
		System.out.printf("p2: (%d, %d, %d) \n",
		p2.getX(), p2.getY(), p2.getZ());
	}
}

执行结果:

p1: (1, 3, 4) 
p2: (0, 0, 0)?

当您扩充某个类别时,该类别的所有public成员都可以在衍生类别中被呼叫使用,而private成员则不可以直接在衍生类别中被呼叫使用;在这个例子 中,Point2D中已经有x, y两个成员,您新增z成员,而方法上您新增一个public的getZ()方法,而getX()与getY()直接继承父类别中已定义的内容。

在扩充某个类别之后,您可以一并初始父类别的建构方法,以完成相对应的初始动作,这可以使用super()方法来达到,它表示呼叫基底类别的建构方法。

父类别的public成员可以直接在衍生类别中使用,而private成员则不行,private类别只限于定义它的类别来存取,如果想要与父类别的 private成员沟通,就只能透过父类别中继承下来的public函式成员,例如上例中的getX()与getY()方法。

下面这个程序是另一个示范存取父类别private成员的方法:

Point2D.java
public class Point2D {
	private int x, y;
	public Point2D() {x = 0; y = 0;}
	public Point2D(int x, int y) {this.x = x; this.y = y;}
	public int getX() {return x;}
	public int getY() {return y;}
	public void setX(int x) {this.x = x;}
	public void setY(int y) {this.y = y;}
}
Point3D.java
public class Point3D extends Point2D { // 继承Point2D类别
	private int z;?// 新增私用资料
	public Point3D() {
		z = 0;
	}
	// 建构函式,同时指定呼叫父类别建构函式
	Point3D(int x, int y, int z) {
		super(x, y);
		this.z = z;
	}
	// 新增函式
	public int getZ() {return z;};
	public void setZ(int z) {this.z = z;}
}
UseExtend.java
public class UseExtend {
	public static void main(String[] args) {
		Point3D p1 = new Point3D(1, 3, 4);
		Point3D p2 = new Point3D();
		System.out.printf("p1: (%d, %d, %d) \n",
		p1.getX(), p1.getY(), p1.getZ());
		p2.setX(2);
		p2.setY(4);
		p2.setZ(6);
		System.out.printf("p2: (%d, %d, %d) \n",
		p2.getX(), p2.getY(), p2.getZ());
	}
}

执行结果:

p1: (1, 3, 4) 
p2: (2, 4, 6) 

父类别的private成员并非无法在衍生类别中使用,而是必须看父类别本身是否提供有可继承使用的管道来存取它们,就如同上例中的public成员 getX()、setX()等方法。