简体   繁体   English

Java中通过接口覆盖的替代方法是什么?

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

The following is impossible in Java, since interfaces don't have implementations: 在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 */ }
}

What I want is for D to inherit C, but not to have to override foo() itself; 我想要的是D继承C,但不必重写foo()本身; rather, I want it to merely indicate "I use the known modification from B". 相反,我希望它仅表示“我使用B的已知修改”。 What's the right idiom in this scenario? 在这种情况下正确的成语是什么?

Notes: 笔记:

  • Yes, I do expect to need to change my design; 是的,我确实确实需要更改我的设计; but change it to what? 但是将其更改为什么? That's what I came here to ask. 那就是我来这里问的。
  • I know Java, please don't re-explain abstract classes and interfaces in your answers. 我知道Java,请不要在您的答案中重新解释抽象类和接口。
  • This should have been possible with multiple inheritance - D could inherit both C and B (assuming no other conflicts). 多重继承应该可以实现-D可以同时继承C和B(假设没有其他冲突)。
  • Java 6 please; 请使用Java 6; Java 7 if absolutely necessary; Java 7(如果绝对必要); Java 8 not relevant for me. Java 8与我无关。
  • The B implementation cannot be moved up into A, since the A implementation really is the default and other classes inherit directly from it (eg class E). B实现不能上移到A,因为A实现实际上是默认的,其他类直接继承自它(例如E类)。
  • C and B are not familiar with each other and cannot mention each other. C和B彼此不熟悉,无法互相提及。
  • The B implementation cannot be moved down into D, since other classes need it which are not familiar with D (eg class F). B实现不能下移到D,因为其他不熟悉D的类(例如F类)也需要它。
  • This is not the diamond problem of multiple inheritance since there's no ambiguity regarding whose implementation is to be used. 这不是多重继承的钻石问题 ,因为对于使用谁的实现没有任何歧义。 Although there is a sort of a diamond pattern A->B,C->D . 尽管有一种菱形图案A-> B,C-> D。

Unless you are using Java 1.8, you cannot have any implementation in the interface, so your question is based on the wrong assumption: You only ever have the implementation of A.foo in C and D . 除非您使用Java 1.8,否则接口中将没有任何实现,因此您的问题基于错误的假设:您只能在CD实现A.foo的实现。

With Java 1.8, you can have so called virtual extension methods in interfaces. 使用Java 1.8,接口中可以具有所谓的虚拟扩展方法 There it should be possible using the following syntax : 应该可以使用以下语法

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();
  }
}

However, since the magic essentially boils down to calling a static method, you can do that for yourself already: 但是,由于魔术本质上可以归结为调用静态方法,因此您可以自己完成此操作:

Create a helper class that provides the default implementation of B.foo using a static void foo(B b) and call it from D.bar via HelperClass.foo(this) . 创建一个使用static void foo(B b)提供B.foo默认实现的帮助程序类,并通过D.bar HelperClass.foo(this)D.bar调用它。

You can solve this problem using multilevel inheritance 您可以使用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
} 

Is this what you're looking for? 这是您要找的东西吗? (This should be in the comments, since I'm not sure what you're looking for, but it doesn't exactly show up nicely there.) (这应该在注释中,因为我不确定您要查找的内容,但是它并不能很好地显示在其中。)

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.*/};
}

Alternatively, if you want B and C to both share methods from A, you would do this... 或者,如果您希望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.*/};
}

If you want A to implement foo(), but not baz(), you would make it abstract, like this... 如果要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.*/};
}

A little crash course about interfaces and abstract classes here... 关于接口和抽象类的一些速成课程...

Java indeed does not have multiple inheritance in the sense that you can only extend one class -- however, you can implement more than one interface. 从您只能扩展一个类的角度来看,Java确实没有多重继承-但是,您可以实现多个接口。

And there are abstract classes. 并且有抽象类。 Say you have: 说您有:

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
}

Also, an abstract class can extend another abstract class: 同样,一个抽象类可以扩展另一个抽象类:

// 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
}

Do not hesitate to ask for more details, I will edit as appropriate. 请随时询问更多详细信息,我将酌情进行编辑。

You probably need a redesign here, but... 您可能需要在这里重新设计,但是...

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

is valid only if interface B declares foo as a method signature ( protected void foo(); ) and if D implements foo (since it would then implement the valid B interface). 仅在interface B foo声明为方法签名( protected void foo(); )并且D实现foo (因为它将随后实现有效的B接口)时才有效。 Thus bar() would then call the foo() method that D implements, since it would be most local to D . 因此, bar()然后将调用D实现的foo()方法,因为它对于D来说是最本地的。

In the scenario one class A should implement the the interface B as well as both have method foo() . 在这种情况下,一个类A应该实现接口B,并且两者都具有方法foo()

Then class C extends A it doesn't have to implement B as it has the default implementation by the superclass. 然后,类C扩展了A,因此不必实现B,因为它具有超类的默认实现。

Then class D extends C and wrapped the method foo() by the method bar() without overriding it. 然后,类D扩展了C,并用方法bar()包装了方法foo() bar()而不覆盖它。 This is idiom. 这是成语。

The code 编码

  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