为什么使用super来调用除被推翻的方法之外的其他方法?

时间:2014-05-26 22:20:39

标签: java inheritance

在oracle教程中,它说: 如果您的方法覆盖了其超类的方法之一,则可以通过使用关键字super来调用重写方法。

它提到了在重写方法中使用super。

但是,事实上,在我编写的示例程序中,我可以使用超级关键字来访问超类中的任何方法。

这里的问题是:为什么大多数人在网上谈论超级的使用,他们总是在谈论覆盖方法的调用?

我的意思是,为什么不建议“使用super来调用超类中的其他方法”?


BTW,这里还有一个问题: 我们不能在静态方法中使用super。编译器不允许我们这样做。

是因为变量“super”属于对象而不是类,就像关键字“this”一样?静态方法属于一个类,静态方法 变量“super”?

5 个答案:

答案 0 :(得分:5)

为什么在方法foo()之外使用super.foo()是一个坏主意

它表明仍然需要旧方法(并且与方法的子版本有所不同),在这种情况下,您可能不应该首先覆盖它。父方法在子对象中仍然“有意义”。

在同一个对象中使用但具有不同效果的两个同名方法听起来像是一个可读性的噩梦。鉴于两者都被使用,它们似乎很可能是使用不同方法名称的单独方法,使它们的细微差别明显。

为什么使用super.foo()来引用未被覆盖的方法是一个坏主意

这在语义上是非常奇怪的事情。父项(非私人)方法 是孩子的方法,除非被覆盖,使用super.method()method()具有相同的效果,所以你没有看到这提到就不足为奇了。正如您所认为的,如果您稍后重写该方法,它也很可能在将来导致错误。

与此类似,您可以将public放在接口方法的前面,但它没有效果。

为什么不能使用super和静态方法

如果父类和子类碰巧具有相同的方法名称,那么就不能覆盖静态方法,就编译器而言,这只是一个巧合(虽然它确实隐藏静态父类中的方法 - 它不会覆盖它)。鉴于无法使用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();
    }
}