[英]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.