当你没有覆盖方法时使用super.method()?

时间:2015-08-22 15:34:28

标签: java methods override super

通常的做法是总是使用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();
    }
}   

感谢您的意见。

6 个答案:

答案 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的版本方法,那么关键字很有用。