我试图摆脱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
以这种方式使用关键字的代码。在这里,我们有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
}
}
问题内容: 当我创建自己的Android自定义类时,它就是本机类。然后,当我要重写基方法,我总是叫方法,就像我一直做的,等 我认为就是这样,因为从一开始,Android团队就建议我们始终调用每个方法重写。 但是,在 许多书籍中, 我可以看到比我自己更有经验的开发人员经常忽略调用,而且我真的怀疑他们是因为缺乏知识而这样做。例如,看看这个基本的SAX,其中解析器类中被省略,并且: 如果尝试通过Ecli
问题内容: 说我有一个像这样的课程: 它具有一个带有扩展它的类的层次结构: 然后在其他地方,我有一堂课利用了这些东西: 我是否可以指定A的子类,以便使用更具体的“某物”类覆盖setSomething方法?这就是我想要做的: 目前,我正在A类中执行以下操作: 如果SuperSomething的类型不适合这些类,则B类和C类在checkClass方法中引发异常。 编辑:我已经尝试使用上述确切的方法签名
问题内容: 我有一个大型的检票口组件库,这些检票口组件使用自定义注释或另一个注释进行注释,该注释具有一个参数以允许多个注释。 这是一个示例代码片段: 到目前为止,我使用apt来检查引用的资源是否确实存在。例如 除非在类路径中找到该文件,否则将导致编译失败。这部分效果很好。 现在,我还是DRY的粉丝,我想使用相同的注释在创建对象时将其实际注入到对象中。使用AspectJ,我已经实现了其中的一部分。
问题内容: 在UIViewController中,此代码: 给出错误 我正在使用Xcode 8 beta 4,且iOS部署目标是9.0,并且在 如何将上面的代码转换为Swift 3? 问题答案: 像这样: …还有其余的。 一般模式 现在,许多Cocoa方法都是属性,因此您可以将它们实现为重写计算变量。因此,从种子3(或更早)移动到种子4的模式是: 更改为 删除 更改为 之所以可行,是因为计算的变量
问题内容: 我更新到Xcode 8 beta 5,现在在从UIView继承的类上收到以下错误: 有解决方法吗? 问题答案: 请检查最新参考。(您只需在Apple开发者网站的搜索栏中输入“ intrinsicContentSize”,就可以轻松找到它。) 宣言 已成为计算属性,因此您需要以这种方式覆盖它: 或者简单地:
我有一个抽象类,割草机,它覆盖了toString()方法。草坪拖拉机类扩展了割草机。它覆盖了toString()方法,并调用super.toString()作为方法的第一行。然后我有一个商业类,它扩展了劳恩拖拉机并覆盖了toString(),也在第一行调用super.toString()。当实例化一个商业对象(声明为割草机对象)并调用它的toString()时,我希望它打印割草机和草坪拖拉机的两个