簡體   English   中英

Java中通過接口覆蓋的替代方法是什么?

[英]What's the alternative in Java for overriding through an interface?

在Java中,以下操作是不可能的,因為接口沒有實現:

class A {
    protected void foo() { /* A impl */ }
    protected void baz() { /* impl */ }
}
interface B {
    /* here's what's impossible to have in Java. */
    protected void foo() { /* B impl incl. call to baz() */ }
}

class C extends A {
    /* stuff that's not in B... */
}

class D extends C implements B {
    void bar() { foo(); /* uses the B impl */ }
}

class E extends A {
    void bar() { foo(); /* uses the A impl */ }
}

class F extends C implements B {
    void bar() { foo(); /* uses the B impl */ }
}

我想要的是D繼承C,但不必重寫foo()本身; 相反,我希望它僅表示“我使用B的已知修改”。 在這種情況下正確的成語是什么?

筆記:

  • 是的,我確實確實需要更改我的設計; 但是將其更改為什么? 那就是我來這里問的。
  • 我知道Java,請不要在您的答案中重新解釋抽象類和接口。
  • 多重繼承應該可以實現-D可以同時繼承C和B(假設沒有其他沖突)。
  • 請使用Java 6; Java 7(如果絕對必要); Java 8與我無關。
  • B實現不能上移到A,因為A實現實際上是默認的,其他類直接繼承自它(例如E類)。
  • C和B彼此不熟悉,無法互相提及。
  • B實現不能下移到D,因為其他不熟悉D的類(例如F類)也需要它。
  • 這不是多重繼承的鑽石問題 ,因為對於使用誰的實現沒有任何歧義。 盡管有一種菱形圖案A-> B,C-> D。

除非您使用Java 1.8,否則接口中將沒有任何實現,因此您的問題基於錯誤的假設:您只能在CD實現A.foo的實現。

使用Java 1.8,接口中可以具有所謂的虛擬擴展方法 應該可以使用以下語法

class ExtenderOfB {
  public static void foo(B b) {
    //...
  }
}

interface B {
  public void foo() default ExtenderOfB.foo;
}

class D extends C implements B {
  public void bar() {
    B.super.foo();
  }
}

但是,由於魔術本質上可以歸結為調用靜態方法,因此您可以自己完成此操作:

創建一個使用static void foo(B b)提供B.foo默認實現的幫助程序類,並通過D.bar HelperClass.foo(this)D.bar調用它。

您可以使用multilevel inheritance來解決此問題

class A
{
    //implementation of A
}

class B extends A
{
  public void foo()
 {
  //you can give your implementation of foo() here
 }
  //includes A's methods also.

}

class C extends B
{
  //will have methods from both A and B
} 

這是您要找的東西嗎? (這應該在注釋中,因為我不確定您要查找的內容,但是它並不能很好地顯示在其中。)

interface A {
    void foo();
    void baz();
}
class B extends A{
    void foo(){/* B's impl. (must be impl.)*/};
    void baz(){/* B's impl. (must be impl.)*/};
}

class C extends A {
    void foo(){/* C's impl. (must be impl.)*/};
    void baz(){/* C's impl. (must be impl.)*/};
}

class D extends C {
    void foo(){/* D's impl */};
    void baz(){/* D's impl, if not included C's impl will be used */};
}

class E extends B {
    void foo(){/* E's impl, if not included B's impl will be used.*/};
    void baz(){/* E's impl, if not included B's impl will be used.*/};
}

或者,如果您希望B和C都共享A的方法,則可以這樣做...

class A {
    void foo(){ /*(must be impl.)*/ };
    void baz(){ /*(must be impl.)*/ };
}

class B extends A {
    void foo(){/* B's impl, if not included A's impl will be used*/};
    void baz(){/* B's impl, if not included A's impl will be used*/};
}

class C extends A {
    void foo(){/* C's impl, if not included A's impl will be used*/};
    void baz(){/* C's impl, if not included A's impl will be used*/};
}

class D extends C {
    void foo(){/* D's impl, if not included C's impl will be used */};
    void baz(){/* D's impl, if not included C's impl will be used */};
}

class E extends B {
    void foo(){/* E's impl, if not included B's impl will be used.*/};
    void baz(){/* E's impl, if not included B's impl will be used.*/};
}

如果要A實現foo()而不是baz(),則可以將其抽象化,如下所示...

abstract class A {
    void foo(){ /*(must be impl.)*/ };
    abstract void baz();
}
class B extends A{
    void foo(){/* B's impl, if not included A's impl will be used*/};
    void baz(){ /*(must be impl.)*/ };
}

class C extends A {
    void foo(){/* C's impl, if not included A's impl will be used*/};
    void baz(){ /*(must be impl.)*/ };
}

class D extends C {
    void foo(){/* D's impl, if not included C's impl will be used */};
    void baz(){/* D's impl, if not included C's impl will be used */};
}

class E extends B {
    void foo(){/* E's impl, if not included B's impl will be used.*/};
    void baz(){/* E's impl, if not included B's impl will be used.*/};
}

關於接口和抽象類的一些速成課程...

從您只能擴展一個類的角度來看,Java確實沒有多重繼承-但是,您可以實現多個接口。

並且有抽象類。 說您有:

interface B {
    void foo();
}

// A is abstract, and it does not implement foo(): this will be left to 
// its inheritors
abstract class A implements B {
    // Method with implementation
    protected void bar() {}
    // Method which must be implemented in inheriting classes
    abstract void baz();
}

// Concrete implementation of A: note that there is no need to specify
// "implements B" since A already does
class C extends A {
    // C must implement baz()  since it is declared abstract in A,
    // but must also implement foo() since A implements B, and A
    // has no implementation of it
}

同樣,一個抽象類可以擴展另一個抽象類:

// D also implements B since A does.
abstract class D extends A {
    // But this time, D implements foo() from B
    @Override
    void foo() {}
}

class E extends D {
    // E must still implement the abstract baz() method declared in A
}

請隨時詢問更多詳細信息,我將酌情進行編輯。

您可能需要在這里重新設計,但是...

class D extends C implements B {
    void bar() {
        foo(); /* used the B impl */
}

僅在interface B foo聲明為方法簽名( protected void foo(); )並且D實現foo (因為它將隨后實現有效的B接口)時才有效。 因此, bar()然后將調用D實現的foo()方法,因為它對於D來說是最本地的。

在這種情況下,一個類A應該實現接口B,並且兩者都具有方法foo()

然后,類C擴展了A,因此不必實現B,因為它具有超類的默認實現。

然后,類D擴展了C,並用方法bar()包裝了方法foo() bar()而不覆蓋它。 這是成語。

編碼

  interface B {
    void foo();
  }

  class A  implements B {
    public void foo() {
      /* B impl */
    }
  }

  class C extends A  {
    /* stuff that's not in B... */
  }

  class D extends C  {
    void bar() {
      foo(); /* used the B impl */
    }
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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