我试图在
Java中获得继承权,并且已经了解到当在子类中重写方法(和隐藏字段)时,仍然可以使用“super”关键字从超类中访问它们.
我想知道的是,’super’关键字是否应该用于非重写方法?
有没有区别(对于非重写方法/非隐藏字段)?
我在下面举了一个例子.
public class Vehicle { private int tyreCost; public Vehicle(int tyreCost) { this.tyreCost = tyreCost; } public int getTyreCost() { return tyreCost; } }
和
public class Car extends Vehicle { private int wheelCount; public Vehicle(int tyreCost,int wheelCount) { super(tyreCost); this.wheelCount = wheelCount; } public int getTotalTyreReplacementCost() { return getTyreCost() * wheelCount; } }
具体来说,假设getTyreCost()没有被覆盖,getTotalTyreReplacementCost()应该使用getTyreCost()还是super.getTyreCost()?
我想知道是否应该在访问超类的字段或方法的所有实例中使用super(在代码中显示您正在访问超类),或者仅在重写/隐藏的那些实例中使用super(因此它们脱颖而出).
解决方法
不要使用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; } }
…并陷入由原始开发人员设置的陷阱以及他们对超级关键字的不寻常使用!
上面的代码不起作用 – 因为在原始的CleverDog实现中,使用super关键字调用getName().这意味着它总是调用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!
当您覆盖方法时,这不是通常的预期行为,因此您应该避免使用不属于它的超级关键字来创建这种混淆.
但是,如果这实际上是您想要的行为,请使用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 } }