在oracle教程中,它说: 如果您的方法覆盖了其超类的方法之一,则可以通过使用关键字super来调用重写方法。
它提到了在重写方法中使用super。
但是,事实上,在我编写的示例程序中,我可以使用超级关键字来访问超类中的任何方法。
这里的问题是:为什么大多数人在网上谈论超级的使用,他们总是在谈论覆盖方法的调用?
我的意思是,为什么不建议“使用super来调用超类中的其他方法”?
BTW,这里还有一个问题: 我们不能在静态方法中使用super。编译器不允许我们这样做。
是因为变量“super”属于对象而不是类,就像关键字“this”一样?静态方法属于一个类,静态方法 变量“super”?
答案 0 :(得分:5)
它表明仍然需要旧方法(并且与方法的子版本有所不同),在这种情况下,您可能不应该首先覆盖它。父方法在子对象中仍然“有意义”。
在同一个对象中使用但具有不同效果的两个同名方法听起来像是一个可读性的噩梦。鉴于两者都被使用,它们似乎很可能是使用不同方法名称的单独方法,使它们的细微差别明显。
这在语义上是非常奇怪的事情。父项(非私人)方法 是孩子的方法,除非被覆盖,使用super.method()
与method()
具有相同的效果,所以你没有看到这提到就不足为奇了。正如您所认为的,如果您稍后重写该方法,它也很可能在将来导致错误。
与此类似,您可以将public
放在接口方法的前面,但它没有效果。
如果父类和子类碰巧具有相同的方法名称,那么就不能覆盖静态方法,就编译器而言,这只是一个巧合(虽然它确实隐藏静态父类中的方法 - 它不会覆盖它)。鉴于无法使用super
关键字覆盖静态方法来访问静态方法变得毫无意义。此外,您可以在Foo中访问静态方法
Foo.staticMethod();
答案 1 :(得分:2)
但是,实际上,在我编写的示例程序中,我可以使用超级关键字来访问超类中的任何方法。
在真实的现实中你不能......除非在非常具体的情况下。
您无法使用super
来调用访问规则禁止的方法:
禁止调用private
方法,除非此类嵌套在另一个中,反之亦然。
禁止调用包私有方法,除非此类与另一个包在同一个包中。
允许调用protected
方法。
如果您的示例似乎与此相矛盾,请将其添加到您的问题中,以便我们可以解释实际情况。
这里的问题是:为什么大多数人在网上谈论超级的使用,他们总是在谈论覆盖方法的调用?
我想你可能在谈论这个:
public class A {
public void foo() {...}
}
public class B extends A {
public void foo() { // The overriding method.
...
super.foo(); // invoking the overridden method.
...
}
}
子类中的方法调用自身的重写版本。您在许多示例中看到它的原因是它是 super
最常见的用例。就是这样。
另一方面,如果方法A.foo()
完全没有被覆盖,那么使用super.foo()
在B
中调用它是合法的......但我不认为这是很好的风格。首先,如果您 在B
中添加覆盖方法,它可能会中断。
答案 2 :(得分:1)
super.f()
绕过this.f()
。如果没有实施this.f()
,则不需要super
。否则,在this.f()
内部调用时会有一些代码味道。
简而言之:g()
调用super.f()
无法找到许多明智的用法:它无法解决任何已知问题。
我只能想到以下内容:布局矩形,使用递归水平列出的框,列出垂直列出的框内的每个框,列出水平列出的框等内容。
public class SpecialBoxLayout extends BoxLayout {
@Override
public void layoutHor(...) {
... // Something extra, special
for
super.layoutVert(...);
...
}
@Override
public void layoutVert(...) {
...
for
super.layoutHor(...);
...
}
这需要继承,方法可以获得额外的功能,并且具有互补的方法。不需要语言功能。与不存在的super.super.f()
一样。
它(g调用super.f)是不好的风格,因为:
layout(Orientation.VERT, ...)
。答案 3 :(得分:0)
您可以使用super.method()
来调用任何方法,但只能使用super()
来调用重写方法。
答案 4 :(得分:0)
假设你有类A和B,其中B扩展A.类A有方法:methodOne(),methodTwo()和类B覆盖methodOne()。但是请记住,类B也有methodTwo(),因为它继承了所以没有用来通过super调用它,因为你直接在后代类中使用它。
编辑让我们来看看:
import java.util.*;
class A {
public void methodOne() {
System.out.println("A.1");
methodTwo();
//super.methodTwo();
/*This above would lead to compilation error even though
it would work as intended - always print A.2.
Use instead for instance: ((A)this).methodTwo();*/
}
public void methodTwo() {
System.out.println("A.2");
}
}
class B extends A{
@Override
public void methodTwo() {
System.out.println("B.2");
}
public B() {
methodOne();
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.methodTwo();
b.methodTwo();
}
}