java包围与过载
此刻让我们用差异的目光来看看本章的头一个例子。在下面这个措施中,要领play()的接口会在被包围的进程中产生变革。这意味着我们实际并没有“包围”要领,而是使其“过载”。编译器答允我们对要领举办过载处理惩罚,使其不陈诉堕落。但这种行为大概并不是我们所但愿的。下面是这个例子:
//: WindError.java
// Accidentally changing the interface
class NoteX {
public static final int
MIDDLE_C = 0, C_SHARP = 1, C_FLAT = 2;
}
class InstrumentX {
public void play(int NoteX) {
System.out.println("InstrumentX.play()");
}
}
class WindX extends InstrumentX {
// OOPS! Changes the method interface:
public void play(NoteX n) {
System.out.println("WindX.play(NoteX n)");
}
}
public class WindError {
public static void tune(InstrumentX i) {
// ...
i.play(NoteX.MIDDLE_C);
}
public static void main(String[] args) {
WindX flute = new WindX();
tune(flute); // Not the desired behavior!
}
} ///:~
这里还向各人引入了另一个易于夹杂的观念。在InstrumentX中,play()要领回收了一个int(整数)数值,它的标识符是NoteX。也就是说,纵然NoteX是一个类名,也可以把它作为一个标识符利用,编译器不会陈诉堕落。但在WindX中,play()回收一个NoteX句柄,它有一个标识符n。即便我们利用“play(NoteX NoteX)”,编译器也不会陈诉错误。这样一来,看起来就象是措施员有意包围play()的成果,但对要领的范例界说却稍微有些不确切。然而,编译器此时假定的是措施员有意举办“过载”,而非“包围”。请仔细体会这两个术语的区别。“过载”是指同一样对象在差异的处所具有多种寄义;而“包围”是指它随时随地都只有一种寄义,只是原先的寄义完全被厥后的寄义代替了。请留意假如遵守尺度的Java定名类型,自变量标识符就应该是noteX,这样可把它与类名区分隔。
在tune中,“InstrumentX i”会发出play()动静,同时将某个NoteX成员作为自变量利用(MIDDLE_C)。由于NoteX包括了int界说,过载的play()要领的int版本会获得挪用。同时由于它尚未被“包围”,所以会利用基本类版本。
输出是:
InstrumentX.play()