[英]Java: calling a super class' protected method from a subclass - not visible?
[英]Java: Calling function in “this” class rather than a subclass (analog to “super”)
在Java中是否有可能以這樣的方式調用可覆蓋的方法:它總是執行“本地定義的”版本而不是從子類中重寫的版本? 也就是說有一個模擬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”,最好不要像反射這樣的技巧。
你的對象是 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
香蕉)! 一旦你有了一個GrannySmithApple
,它就不再是Apple
了,除非你可以用普通的Apple
( printColor
, eat
等)做一切相同的事情。有意義嗎? 從常規Apple
到GrannySmithApple
的轉換之間沒有任何變化,顯然仍然是相同的。
你可以在A中調用一個“內部” 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()
現在將打印“Foo from A”,而new B().foo()
將打印“Foo from B”。
foo()
總是調用new ...
語句中使用的類的實例方法。
總之,我認為你的問題的答案是否定的 ,不能做到。 它會阻止您完全覆蓋部分行為。
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() {
...
}
}
據我所知, B
對象總是調用自己的foo()
方法。 話雖如此,可以定義B.foo()
來調用超類' foo()
方法。 例如,您可以按如下方式定義B
:
class B extends A {
@Override public void foo() {
super.foo();
}
}
而這樣做將有B
調用foo
從A
。 但這樣做會讓它始終如此。
有這個經驗法則:
In Inheritance the most specific version of the method for that class is called.
-因此,如果在B的實例上調用它,將始終調用Class B
的foo()
方法。
-仍然如果你想使用上面提到的代碼調用Class A
的foo()
方法,那么你將需要super
關鍵字。
例如:
class B extends A {
@Override
void foo() {
super.foo();
}
}
this
引用了“這個對象”,而不是“這個類”。
這意味着,如果你有一個對象B
擴展A
,當它執行超的方法A
是提到this
,它實際上指向的實例B
,因此將執行的方法B
。
您可以將A
中的方法視為默認方法 。 如果在實際對象B
重寫該方法,則將始終調用它。
我建議你改變你的設計並使用組合而不是繼承 :這將確保明確分離關注點,並使你的代碼更容易理解和測試。
正如其他人所說,沒有直接的方法可以做到這一點,但你可能會考慮這個結構的變體:
void bar() {
ClassA self = new ClassA();
self.foo(); // <-- This is the important line!
}
要么使你的方法靜態(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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.