簡體   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