不要使用super
关键字来引用其他未被覆盖的方法。它使其他试图扩展您的类的开发人员感到困惑。
让我们看一些确实以这种方式使用super
关键字的代码。这里我们有 2 个类:Dog
和CleverDog
:
/* file Dog.java */
public static class Dog extends Animal {
private String name;
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
/* file CleverDog.java */
public class CleverDog extends Dog {
public CleverDog(String name) {
super(name);
}
public void rollover() {
System.out.println(super.getName()+" rolls over!");
}
public void speak() {
System.out.println(super.getName() + " speaks!");
}
}
现在,假设您是该项目的新开发人员,并且您需要为电视上的一只聪明的狗提供一些特定的行为:这只狗必须完成所有的把戏,但应该使用它虚构的电视名称。为此,您覆盖该getName(...)
方法...
/* file DogOnTv.java */
public class DogOnTv extends CleverDog {
String fictionalName;
public DogOnTv(String realName, String fictionalName) {
super(realName);
fictionalName = fictionalName;
}
public String getName() {
return fictionalName;
}
}
...并落入由原始开发人员设置的陷阱以及他们对super
关键字的不寻常使用!
上面的代码不起作用 - 因为在原始CleverDog
实现中,是使用关键字getName()
调用的。super
这意味着它总是调用Dog.getName()
- 与任何覆盖无关。因此,当您使用新DogOnTv
类型时...
System.out.println("Showcasing the Clever Dog!");
CleverDog showDog = new CleverDog("TugBoat");
showDog.rollover();
showDog.speak();
System.out.println("And now the Dog on TV!");
DogOnTv dogOnTv = new DogOnTv("Pal", "Lassie");
dogOnTv.rollover();
...你得到错误的输出:
Showcasing the Clever Dog!
Tugboat rolls over!
Tugboat speaks!
And now the Dog on TV!
Pal rolls over!
Pal speaks!
super
当你重写一个方法时,这不是通常的预期行为,所以你应该避免在不属于它的地方使用关键字造成这种混乱。
但是,如果这实际上是您想要的行为,请改用final
关键字 - 以清楚地表明该方法不能被覆盖:
/* file CleverDog.java */
public class CleverDog extends Dog {
public CleverDog(String name) {
super(name);
}
public final String getName() { // final so it can't be overridden
return super.getName();
}
public void rollover() {
System.out.println(this.getName()+" rolls over!"); // no `super` keyword
}
public void speak() {
System.out.println(this.getName() + " speaks!"); // no `super` keyword
}
}