通常的做法是总是使用super来调用超类中的方法,即使我没有覆盖该方法吗?
假设
public class Parent{
public void method() {
}
}
所以
public class Child extends Parent {
public void someMethod() {
super.method();
}
}
或
public class Child extends Parent {
public void someMethod() {
method();
}
}
感谢您的意见。
答案 0 :(得分:4)
调用super
告诉JVM 明确地查看父类'方法的版本。继续你的例子,如果你只是打电话
method()
在查看父类之前,JVM将首先在调用类中搜索该方法(在本例中为Child
)。另一方面,如果你打电话
super.method()
然后JVM将显式查看实现的父类,即使Child
有一个名为method()
的方法。
将这两个想法放在一起,当你打算打电话给父类时,你应该总是使用super
。方法。如果您的课程没有覆盖该方法,那么您可以在没有super
的情况下进行呼叫。但是,如果有人稍后重构你的课程并覆盖该方法,即使这也会成为问题。
答案 1 :(得分:2)
通常使用super来调用超类中的方法吗?还是冗余代码?
这不是多余的。它有一个特殊的目的是调用父类方法(虽然你是ovveriden )。当你不想要时,不要调用。如果您当前的班级不是该班级的孩子,super
不会为您工作。
此外,如果你调用一个重写的supermethod,它是使用supermethod还是最低的方法?(在继承树中)
重写方法。因为你在班上重写了它。
答案 2 :(得分:2)
领先的问题很容易回答:
通常的做法是总是使用super来调用超类中的方法,即使我没有覆盖该方法吗?
不,这不常见。相反,它危险地混淆这样做。您可以正常调用方法,因为继承的主要目的是允许类重写方法来更改/扩展其行为。您通常不关心实际实施方法的级别。
明显的例外是当你做自己覆盖方法并且想要/需要父母功能时。
现在明确调用super:
的危险混乱部分public class CallSuper {
static class Parent {
public void foo() {
System.out.println("Parent.foo");
}
/**
* Calls foo to do the main work
*/
public void bar() {
System.out.print
foo();
}
}
static class Child extends Parent {
public void foo() {
System.out.println("Child.foo");
}
public void bar() {
super.foo();
}
}
static class GrandChild extends Child {
public void foo() {
System.out.println("GrandChild.foo");
}
}
public static void main(String[] args) {
Parent p = new Parent();
Parent c = new Child();
Parent g = new GrandChild();
System.out.print("Parent.foo() = ");
p.foo();
System.out.print("Child.foo() = ");
c.foo();
System.out.print("GrandChild.foo() = ");
g.foo();
System.out.print("Parent.bar() = ");
p.bar();
System.out.print("Child.bar() = ");
c.bar();
System.out.print("GrandChild.bar() = ");
g.bar();
}
}
如果您运行此示例,它将输出(为清晰起见,添加了行号):
1 Parent.foo() = Parent.foo
2 Child.foo() = Child.foo
3 GrandChild.foo() = GrandChild.foo
4 Parent.bar() = Parent.foo
5 Child.bar() = Parent.foo
6 GrandChild.bar() = Parent.foo
前四行并不奇怪,我们得到foo在每个级别实现的内容,分别是父母的酒吧调用它的foo。它在第5行开始变得奇怪。孩子通过调用super.bar()来绕过它自己的foo覆盖,所以虽然它的foo()是专用的,但是bar()不是。在第6行中,你看到GrandChild继承了Child的这种奇怪之处,所以在Child's bar中看起来有些无辜的super.foo()已经破坏了GrandChild的预期,即它对foo()的覆盖是有效的所有bar()也是。
现在,如果您想象foo()和bar()实际上正在做一些有用的并且他们彼此之间有一个有意义的关系,例如你被引导相信(通过父级的文档或只是常识),重写foo()也会改变bar()的行为。孩子"超级"打破了。
根据经验,如果你看到" super.x()"在" x()"的实际覆盖之外的任何地方打电话,这可能是潜伏发生的事故。
答案 3 :(得分:1)
如果你没有凌驾,我们来谈谈表现。
如果你在类中调用一个继承的方法,比方说methodInSuperclass()
,JVM将首先在你的类中查找该方法,然后在类层次结构中查找它,直到找到它为止。
使用super.methodInSuperclass()
告诉JVM直接转到超类来查找该方法。
因此,使用super
关键字可以提高几个工厂的性能。这是一个丑陋的代码,但它并不是多余的,因为它会带来一些性能提升。
如果时间紧迫,请考虑使用它。
答案 4 :(得分:0)
调用超级方法完全取决于你想要做什么。如果你想做父类所做的事情加上一些额外的动作,那么调用super方法是好的。如果您在子实现中执行完全不同的操作,则不要调用super方法。当您在类的层次结构中调用super方法时,它会调用层次结构中与您的子类最接近的方法。
在某些情况下,您可能拥有一个API,其中调用super方法是整个合同的一部分。 clone
方法就是这种情况。
答案 5 :(得分:0)
如果Child与Parent具有相同的版本方法,如果没有" super",JVM将调用Child的版本而不是Parent的版本。 "超级"如果您想确保Child始终调用Parent的版本方法,那么关键字很有用。