2010-08-11 125 views
31

比方說,我有三個類A,B和C超級調用父類方法

  • B擴展一個
  • ç延伸乙

所有定義一個public void foo()方法。

現在來自C的foo()方法我想調用A的foo()方法(不是它的父B的方法,而是超級超類A的方法)。

我試過super.super.foo();,但它的語法無效。 我該如何做到這一點?

+1

正因爲有人要問,爲什麼C擴展B,如果你似乎希望它直接擴展A? (我想還有其他部分你依賴於B的功能,或者其他東西) – 2010-08-11 07:46:25

+0

只有在B沒有覆蓋A的foo()時,才能使用super.foo()從C調用A的foo()。 – YoK 2010-08-11 08:02:25

+1

_Effective Java第2版,第16項:贊成繼承inheritance_。另外,檢查裝飾者模式;它可能更適合您的需要。 – polygenelubricants 2010-08-11 08:47:58

回答

30

你甚至不能使用反射。像

Class superSuperClass = this.getClass().getSuperclass().getSuperclass(); 
superSuperClass.getMethod("foo").invoke(this); 

東西會導致InvocationTargetException,因爲即使你呼籲superSuperClass foo的方法中,它仍然會使用C.foo()當您指定的調用「這個」。這是所有Java方法都是虛擬方法的結果。

看來你需要B類的幫助(例如定義一個superFoo(){ super.foo(); }方法)。

也就是說,如果您嘗試這樣的設計,看起來像是一個設計問題,所以給我們一些背景會有幫助:爲什麼您需要這樣做?

+1

這不是我的要求。我只是想盡一切辦法繼承和繼承這個問題。謝謝..我得到了答案 – Harish 2010-08-19 06:18:40

+0

嗯,我需要這樣做,因爲超類以一種我不想要的方式覆蓋超級超類...它是一個庫...所以我想打電話給超級超類超類...也許採取超級超類的方法的源代碼,重寫再次解決這個問題? – xdevs23 2016-03-15 15:43:08

+0

當然,你可以在你的方法中編寫你想要的東西,所以在這種情況下,複製代碼應該可行。但是,如果super-super-class在'foo()'中使用私有或包私有字段或方法,則需要反射才能訪問這些字段或方法(當然,如果安全管理器已安裝,則不幸運)。此外,如果最初的'foo()'代碼自己調用'super',它也不起作用。 – Landei 2016-03-16 16:56:55

0

這是不可能的,我們僅限於調用超類的實現。

+0

(我太被亞倫現在刪除的答案留下深刻的印象我在發佈兩秒後刪除了我的內容;) - 刪除了它,即使現在有更好的答案) – 2010-08-11 08:32:04

19

你不能 - 因爲它會破壞封裝。

你可以調用你的超類的方法,因爲它假定你知道什麼會破壞你自己的類中的封裝,並避免這種情況......但是你不知道你的超類執行什麼規則 - 所以你不能繞過這裏的實現。

+0

奇怪..我記得有一種方法可以調用Object。toString()即使toString()被超類重載。但是'Type.this'不能編譯。 : -/ – 2010-08-11 07:34:20

+1

@Aaron:我不確定Object.toString() - 你在想'System.identityHashCode'嗎? – 2010-08-11 07:35:24

+0

從來沒有使用過,我很確定它是toString()。 Object.super.toString()也不起作用。也許這是Java早期版本中的一個錯誤。 – 2010-08-11 07:39:03

3

你不能以簡單的方式做到這一點。

這是我認爲你可以這樣做:

有一個布爾在您的類B.現在,您必須調用B的由C foo的喜歡[super foo]但這樣做在此之前設定的布爾爲true。現在在B的foo中檢查bool是否爲真,然後不要執行任何步驟,只需調用A的foo。

希望這會有所幫助。

+6

這是最瘋狂的Java破解:) – 2010-08-11 07:40:38

+2

Jon Skeet的答案是最好的:這種功能不應該啓用,因爲它打破封裝。我們應該解決_WHY_問題,而不是解決_HOW_做這樣的事情,那麼任何人都會想要做這樣的事情(並且因違反OOP原則而撕裂這個論點)。 – polygenelubricants 2010-08-11 07:41:49

+2

@Nikita Rybak:人們要求不應該被問到的事情。因此,不應該給出的答案;) – 2010-08-11 07:42:38

0

smell東西很腥。

你確定你不只是推動信封太「只是因爲你應該能夠做到這一點」?你確定這是你可以得到的最好的設計模式嗎?你有沒有嘗試重構它?

0

我有一個問題,超類會調用被覆蓋的頂級方法。 這是我的解決方法...

//這會失敗致電超類方法爲A1()將調用的頂級方法

class foo1{ 
public void a1(){ 
    a2(); 
    } 
public void a2(){} 
} 
class foo2 extends foo1{ 
{ 
public void a1(){ 
//some other stuff 
super.a1(); 
} 
public void a2(){ 
//some other stuff 
super.a2(); 
} 

//這保證了RIGHT SUPERCLASS方法被稱爲 //公有方法只調用私有方法,因此所有公共方法可以被覆蓋而不影響超類的功能。

class foo1{ 
public void a1(){ 
    a3();} 
public void a2(){ 
    a3();} 
private void a3(){ 
//super class routine 
} 
class foo2 extends foo1{ 
{ 
public void a1(){ 
//some other stuff 
super.a1(); 
} 
public void a2(){ 
//some other stuff 
super.a2(); 
} 

我希望這有助於。 :)

+0

這實際上並沒有回答這個問題。請重讀這個問題。 – Aboutblank 2013-04-16 16:38:48

0

使用反射API之前,請考慮它的成本。

這很容易做到。例如:

B的B子類和B子類的A子類。三者都有方法methodName()。

public abstract class A { 

    public void methodName() { 
    System.out.println("Class A"); 
    } 

} 


public class B extends A { 

    public void methodName() { 
     super.methodName(); 
     System.out.println("Class B"); 
    } 

    // Will call the super methodName 
    public void hackSuper() { 
     super.methodName(); 
    } 

} 

public class C extends B { 

    public static void main(String[] args) { 
     A a = new C(); 
     a.methodName(); 
    } 

    @Override 
    public void methodName() { 
     /*super.methodName();*/ 
     hackSuper(); 
     System.out.println("Class C"); 
    } 

} 

運行C級輸出將是: A類 C類

相反的輸出: A類 B類 C類

2

引述先前的回答:「你可以」 t - 因爲它會破壞封裝。「我想補充一點:

但是,有一個角落的情況下,你可以,即如果方法是staticpublicprotected)。你不能overwrite the static method

有一個public static方法是微不足道的證明你確實可以做到這一點。

但對於protected,您需要從您的某個方法中對繼承路徑中的任何超類執行強制轉換,並調用該超類方法。

這是角落情況下,我在我的答案探索:

public class A { 
    static protected callMe(){ 
     System.out.println("A"); 
    } 
} 

public class B extends A { 
    static protected callMe(){ 
     System.out.println("B"); 
    } 
} 

public class C extends B { 
    static protected callMe(){ 
     System.out.println("C"); 
     C.callMe(); 
    } 

    public void accessMyParents(){ 
     A a = (A) this; 
     a.callMe(); //calling beyond super class 
    } 
} 

答案依然還是沒有,只是想表明的情況下就可以了,雖然它可能會沒有任何意義和只是一個練習。

2

是的,你可以做到這一點。這是一個黑客。儘量不要這樣設計你的程序。

class A 
{ 
    public void method() 
    { /* Code specific to A */ } 
} 

class B extends A 
{ 
    @Override 
    public void method() 
    { 
     //compares if the calling object is of type C, if yes push the call to the A's method. 
     if(this.getClass().getName().compareTo("C")==0) 
     { 
      super.method(); 
     } 
     else{ /*Code specific to B*/ } 

    } 
} 

class C extends B 
{ 
    @Override 
    public void method() 
    { 
     /* I want to use the code specific to A without using B */ 
     super.method(); 

    } 
} 
+0

這就是所謂的控制反轉! – 2018-01-29 01:44:18