ITEEDU

Java Gossip: 重新定义(Override)方法

类别是对象的定义书,如果原来的定义并不符合您的需求,您可以在扩充类别的同时重新定义,举个例子来说,看看下面这个类别:

public class SimpleArray {
	protected int[] array;
	public SimpleArray(int i) {
		array = new int[i];
	}
	public void setElement(int i, int data) {
		array[i] = data;
	}
	....
}

这个类别设计一个简单的数组辅助类别,不过您觉得它的setElement()方法不够安全,您想要增加一些数组的边界检查动作,于是扩充该类别, 并重新定义setElement()方法:

public class SafeArray extends SimpleArray {
	public SafeArray(int i) {
		super(i);
	}
	public void setElement(int i, int data) {
		if(i < array.length)
		super.setElement(i, data);
	}
	....
}

这么以来,以SafeArray类别的定义所产生的对象,就可以使用新的定义方法。

当同一个成员方法在衍生类别中被重新定义,使用此衍生类别所生成的对象来呼叫该方法时,所执行的会是衍生类别中所定义的方法,而基底类别中的同名方法并不受影响。

在上面您看到super()与super, 如果您在衍生类别中想要呼叫基底类别的建构方法,可以使用super()方法,另外若您要在衍生类别中呼叫基底类别方法,则可以如使用 super.methodName(),就如上面所示范的,但使用super()或super呼叫父类别中方法的条件是父类别中的该方法不能是 "private"。

重新定义方法时要注意的是,您可以增大父类别中的方法权限,但不可以缩小父类别的方法权限,例如在扩充SimpleArray时,您不可以这么作:

public class SafeArray extends SimpleArray {
	....
	private void setElement(int i, int data) {
		....
	}
}

尝试将setElement()方法从"public"权限缩小至"private"权限是不行的,编译器会回报以下的错误讯息:

Test.java:18: setElement(int,int) in SafeArray cannot override setElement(int,in t) in SimpleArray; attempting to assign weaker
 accessprivileges; was public
private void setElement(int i, int data) {
^
1 error


从 J2SE 5.0 之后,在重新定义方法时,您可以重新定义返回值,例如您原先设计了一个Point2D类别:

public class Point2D {
	protected int x;
	protected int y;
	public Point2D(int x, int y) {
		this.x = x;
		this.y = y;
	}
	public Point2D getCopyOfMe() {
		return new Point2D(x, y);
	}
}
....

现在您扩充它,定义了一个Point3D类别:

public class Point3D extends Point2D {
	protected int z;
	public Point3D(int x, int y, int z) {
		super(x, y);
		this.z = z;
	}
	public Point3D getCopyOfMe() {
		return new Point3D(x, y, z);
	}
}
....

在J2SE 5.0之前,您会很苦恼于不能重新定义返回值,因此您势必要重新写一个方法名称来传回Point3D的返回值,但是在J2SE 5.0之后,重新定义返回值是可行的了,但使用时还是有限制条件,也就是重新定义的返回值型态必须是父类别中同一方法返回型态的子类别,或者是实作接口的类别,例如以下是可行的:

public interface ISome {
	....
}
public class SomeImpl implements ISome {
	....
}
public class Other {
	public ISome doSomething() {}
}
public class SubOther {
	public?SomeImpl doSomething() {}
}

注意!您无法重新定义static方法,一个方法要被重新定义,它必须是非static的,如果您在子类别中定义一个有同样签署(signature)的static成员,那不是重新定义,那是定义一个属于该子类别的static成员。