簡體   English   中英

Java:在“this”類中調用函數而不是子類(類似於“super”)

[英]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了,除非你可以用普通的AppleprintColoreat等)做一切相同的事情。有意義嗎? 從常規AppleGrannySmithApple的轉換之間沒有任何變化,顯然仍然是相同的。

你可以在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調用fooA 但這樣做會讓它始終如此。

有這個經驗法則:

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

-因此,如果在B實例上調用它,將始終調用Class Bfoo()方法。

-仍然如果你想使用上面提到的代碼調用Class Afoo()方法,那么你將需要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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM