繁体   English   中英

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

[英]Using super.method() when you're not overriding the method?

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

感谢您的输入。

调用super告诉JVM 明确查看父类的方法版本。 继续你的例子,如果你只是打电话

method()

在查看父类之前,JVM将首先在调用类中搜索该方法(在本例中为Child )。 另一方面,如果你打电话

super.method()

然后JVM将显式查看实现的父类,即使Child有一个名为method()

将这两个想法放在一起,当你打算调用父类的方法时,你应该总是使用super 如果您的类没有覆盖该方法,那么您可以在没有super情况下调用。 但是如果有人稍后重构你的类并覆盖该方法,那么即使这也会成为问题。

通常的做法是总是使用super来调用超类中的方法吗? 还是冗余代码?

这不是多余的。 它有一个特殊目的,即调用父类方法( 尽管你是ovveriden )。 如果您不想要,请不要调用。 如果您当前的课程不是该课程的孩子,那么super将不适合您。

此外,如果你调用一个重写的supermethod,它是使用supermethod还是最低的方法?(在继承树中)

被重写的方法。 因为你在课堂上重写了它。

领先的问题很容易回答:

通常的做法是总是使用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()实际上做了一些有用的事情,并且他们彼此之间有了一个有意义的关系,例如,你被引导相信(通过Parent的文档或只是常识),重写foo()将改变bar()的行为也是如此。 孩子的“超级”打破了这一点。

根据经验,如果你在“x()”的实际覆盖之外的任何地方看到“super.x()”调用,它可能是潜伏发生的事故。

如果你不是压倒一切,那就谈谈性能吧。

如果你在类中调用一个继承的方法,比方说, methodInSuperclass() ,JVM将首先在你的类中查找该方法,然后向上查找类层次结构,直到找到它为止。

使用super.methodInSuperclass()告诉JVM直接转到超类来查找该方法。

因此,使用super关键字可以提高几个工厂的性能。 这是一个丑陋的代码,但它并不是多余的,因为它会带来一些性能提升。

如果时间紧迫,请考虑使用它。

是否调用超级方法完全取决于您要做的事情。 如果你想做父类所做的事情加上一些额外的动作,那么调用super方法是好的。 如果你在子实现中做了一些完全不同的事情,那么不要调用super方法。 当您在类的层次结构中调用super方法时,它会调用层次结构中与您的子类最接近的方法。

在某些情况下,您可能有一个API,其中调用super方法是整个合同的一部分。 clone方法就是这种情况。

如果Child与Parent具有相同的版本方法,如果没有“super”,JVM将调用Child的版本而不是Parent的版本。 如果要确保Child始终调用Parent的版本方法,则“super”关键字很有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM