2012-11-15 27 views
3

是否有可能在Java中調用可重寫的方法,使得它始終執行「本地定義的」版本而不是從子類重寫版本?即有沒有類似super這個類,而不是超類?Java:在「this」類中調用函數而不是子類(類似於「super」)

讓我給一個代碼示例,希望能夠說清楚我想要做的事:

class A { 
    void foo() { 
     System.out.println("Foo from A"); 
    } 

    void bar() { 
     foo(); // <-- This is the important line! 
    } 
} 

class B extends A { 
    @Override 
    void foo() { 
     System.out.println("Foo from B"); 
    } 
} 

如果我做new B().bar(),它會調用A定義的bar()方法,它調用foo()作爲覆蓋在B中打印「Foo from B」。

有沒有一種方法可以強制bar()方法調用A中定義的foo()方法,而不是B?就像我可以在B中使用super.foo()來調用A中定義的foo()方法?不幸的是,使用this.foo()仍然會調用子類的版本。即使像((A) this).foo()A.this.foo()不起作用。

顯然,我可以在A中簡單定義一個私人或最終版本foo(),然後調用它。但我希望有一個解決方案,我所做的就是將上面的代碼示例中的「重要線條」更改爲調用foo()以使其打印「Foo from A」的不同方式,最好不需要像反射一樣的技巧。

+0

調用哪個'foo()'是由**值**(實例)的類型決定的,而不是由**變量**,i的類型決定的。即'A a = new B(); a.foo();'調用'B.foo()'。 – nalply

+1

看起來您發現了許多(許多)繼承問題。你最好使用組合而不是繼承,這會產生一個更容易閱讀,理解和弄清楚它在做什麼的代碼。 – Guillaume

+0

@Guillaume我很驚訝,這並不足以解決問題。我正在考慮所有的基類型類,例如OutputStream,它們通過將writeback(byte [] b)轉發給write(int b)來提供回退方法實現。如果兩者都覆蓋,則不能再使用超級來利用回退。 –

回答

0

要麼讓你的方法靜態(baadddddd),要麼改變你的設計。

事實上,爲子類定義自適應相關方法的默認行爲是沒有意義的。

隨着你foo()方法似乎有所不同,你可以實現一個策略模式是這樣的:

interface BarProcess{ 
    void foo(); 
} 

public class DefaultBarProcess implements BarProcess{ 
    void foo() { 
     System.out.println("Foo from A"); 
    } 
} 

public class AnotherBarProcess implements BarProcess{ 
    void foo() { 
     System.out.println("Foo from B"); 
    } 
} 

class A { 

    private BarProcess barProcess; 

    public A(Bar barProcess){ 
     this.barProcess = barProcess; 
    } 

    void bar() { 
     barProcess.foo(); 
    } 
} 

class B extends A { //deprecated! No need to exist 

} 
0

foo()始終調用new ...語句中使用的類的實例方法。

總之,我認爲你的問題的答案是NO,它不能做到。它會阻止你完全覆蓋部分行爲。

class A { 

method1() { 
... 
method2(); 
... 
} 

class B extends A { 

// You can override method2 here to change the behaviour of method1 
// because it will call **your** version of method2 
// You **don't** have to override method1 to achieve that 

method2() { 
... 
} 

} 
0

據我所知,B對象總是會調用它自己foo()方法。有了這個說法,B.foo()可以被定義爲調用超類'foo()的方法。例如,你可以定義B如下:

class B extends A { 
    @Override public void foo() { 
     super.foo(); 
    } 
} 

而且這樣做將有B呼叫fooA。但這樣做總會這樣做。

+0

Java對'me'或'here'或'local'或'this'或類似的東西提供'超級'但不提供模擬,這讓我很奇怪...... –

+0

Java有'this'關鍵字... – Whymarrh

+0

是但是「this」表示這個對象,而不是這個類......所以如果對象是B,這實際上會調用B上的方法(即使它是從A調用的) – Guillaume

0

有這個經驗法則:

In Inheritance the most specific version of the method for that class is called. 

-因此,這將是永遠的Class Bfoo()方法將被調用,如果基於B的實例調用。

-不過,如果你想的Class Afoo()方法使用上述代碼,那麼你將需要super關鍵字調用。

如:

class B extends A { 
    @Override 
    void foo() { 

     super.foo(); 
    } 
} 
1

你的對象一個B。它不是A!這裏有一個例子:

public class Apple { 
    public void printColor() { 
     System.out.println("I am red"); 
    } 

    public void bar() { 
     printColor(); 
    } 
} 

然後子類:

public class GrannySmithApple extends Apple { 
    public void printColor() { 
     System.out.println("I am green"); 
    } 
} 

GrannySmithApple小號是綠色,總是(除非他們都爛了,但這是香蕉完全是另外一個也可以)!一旦你有一個GrannySmithApple,這是不是Apple了,除非你可以用它做所有相同的事情,你可以經常AppleprintColor,,eat等)有意義嗎?而在從常規AppleGrannySmithApple的轉換之間沒有任何變化的東西顯然仍然相同。

0

this引用「this object」,而不是「this class」。

這意味着,如果你有一個擴展A對象B,當它執行超A是提到this的方法,它實際上指向的B的實例,因此將執行上B方法。

您可以將A中的方法看作默認方法。如果該方法在您的實際對象B中被覆蓋,那麼將調用始終調用

我建議你改變設計並使用組成,而不是繼承:這將確保一個值得關注的清晰分離,使你的代碼有很多更容易理解和測試。

0

正如其他人說沒有直接的辦法做到這一點,但你可能會考慮這個結構的變體:

void bar() { 
    ClassA self = new ClassA(); 
    self.foo(); // <-- This is the important line! 
    } 
+0

不幸的是,foo()將失去對所有局部變量的訪問。但是「自我」會成爲這個場景中使用的關鍵詞! :) –

1

你可以有一個「內部」在一個名爲foo()

class A { 
    private void fooInternal() { 
     System.out.println("Foo from A"); 
    } 

    void foo() { 
     fooInternal(); 
    } 

    void bar() { 
     fooInternal(); 
    } 
} 

class B extends A { 
    @Override 
    void foo() { 
     System.out.println("Foo from B"); 
    } 
} 

new B().bar()現在將打印 「富從A」,而new B().foo()將打印 「富從B」。

+0

@ Mik378你能否解釋一下,如果調用'new B().bar()',重寫的方法將會被調用。 – maba

+0

這會工作。這就是我在我的問題最後一段開始時的意思,它可能是一個可能的但並非如此優雅的解決方案。 –

+0

你認爲在這裏會有什麼作用?如果從子類對象調用它,仍然會調用在子類中被重寫的方法。你**沒有達到任何**這個構造 –

相關問題