【问题标题】:What's the alternative in Java for overriding through an interface?Java中通过接口覆盖的替代方法是什么?
【发布时间】:2012-12-20 08:21:50
【问题描述】:

在 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 类)需要它。
  • 这不是多重继承的diamond problem,因为对于要使用谁的实现没有歧义。虽然有一种菱形图案 A->B,C->D 。

【问题讨论】:

  • interface B 不能有实现,只有方法签名。所以A应该是唯一有效的??
  • 您不能继承two 类。所以重新检查你的程序设计来解决这个问题。
  • 你不是在找抽象类吗?
  • "B 实现不能上移到 A 中,因为 A 实现确实是默认的,其他类直接继承自它(例如 E 类)。" B 不能有一个实现。它是一个接口,根据定义,它缺乏实现。你的问题没有意义,因为你一直坚持 B 已经实现了方法,这对于接口是不可能的。如果你想让B实现方法,它必须是一个类。
  • 您说“在 Java 中以下是不可能的,因为接口没有实现:”,但这就是接口的全部意义所在。你还不如做一个变量final,然后抱怨你不能改变这个变量。这就像说“这个正方形是一个坏正方形,因为我把它做成了圆形。”那为什么要绕圈呢?把它做成一个正方形就行了。你故意阻止自己做某事,然后抱怨你不能做那件事。

标签: java inheritance interface multiple-inheritance


【解决方案1】:

这就是你要找的吗? (这应该在 cmets 中,因为我不确定您在寻找什么,但它并没有很好地显示在那里。)

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

【讨论】:

  • 不,不是……C和B互不知情,不能互相提及。
  • C 知道 B,它扩展了 B。但是不,B 不知道 C。如果你调用 C.foo() 但没有实现 C.foo(),B.foo( ) 将被执行。
  • 编辑使 C 实现 A 而不是扩展 B。
【解决方案2】:

在场景中,一个类 A 应该实现接口 B,并且两者都有方法 foo()

然后类 C 扩展 A 它不必实现 B,因为它具有超类的默认实现。

然后类 D 扩展 C 并通过方法 bar() 包装方法 foo() 而不覆盖它。这是成语。

代码

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

【讨论】:

    【解决方案3】:

    这里有一个关于接口和抽象类的速成课程...

    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
    }
    

    不要犹豫,询问更多细节,我会酌情编辑。

    【讨论】:

    • 这不符合我的要求,因为:1. D 有一个不特定于它的 foo() 实现(例如,由其他类“实现”我不可能的接口 B 共享) 2.接口的 foo() 可能取决于 A ;一般来说,B 可能依赖于 A,即使没有继承它。
    • 嗯,你知道,你也可以让接口扩展其他接口。呸,我会尝试的。
    【解决方案4】:

    您可能需要在这里重新设计,但是...

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

    仅当interface Bfoo 声明为方法签名(protected void foo();) 并且D 实现foo 时才有效(因为它将实现有效的B 接口)。因此bar() 将调用foo() 实现的D 方法,因为它对于D 来说是最本地的。

    【讨论】:

    • D 自身无法实现 foo。实现必须在 B 中,因为多个类需要相同的实现,而且他们不熟悉 D,只熟悉 A 和 B。
    • D 必须实现foo,如果它实现了BBfoo 声明为接口方法签名,因此任何实现类都必须实现foo 方法。实现不能B 中,因为B 是一个接口,因此不能实现任何方法。不知道你所说的多个类只熟悉AB 是什么意思。您可以使任何类“熟悉”Java 中的任何其他类。
    • 您的回答是我必须不编写我需要编写的代码....我正在寻找使用接口的替代方法 .
    • @einpoklum 这就是每个人都在说的,你的接口问题的替代方案是使用一个每个人都已经给你的类作为解决方案。
    【解决方案5】:

    你可以使用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
    } 
    

    【讨论】:

    • @einpoklum 要么B 必须是一个类,如果Binterface,那么实现类必须提供它的实现。
    • 但这就是我遇到的问题。 B 不能是类,因为 Java 没有多重继承,但它不能是接口,因为接口没有实现。
    • 这就是我要说的,因为 Java 不支持 Multiple Inheritance,你将让你改变你的实现设计。
    • 好吧,问题是:改成什么?
    • B 更改为abstractconcrete 类并实现多级继承,然后就可以了。
    【解决方案6】:

    除非您使用 Java 1.8,否则接口中不能有任何实现,因此您的问题是基于错误的假设:您在 CD 中只有 A.foo 的实现。

    在 Java 1.8 中,您可以在接口中拥有所谓的虚拟扩展方法。应该可以使用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();
      }
    }
    

    但是,由于魔术本质上归结为调用静态方法,您已经可以自己做:

    创建一个辅助类,使用static void foo(B b) 提供B.foo 的默认实现,并通过HelperClass.foo(this)D.bar 调用它。

    【讨论】:

    • 你的建议行不通(我认为),因为这些都是非静态方法。
    • @einpoklum 该问题使用非静态方法,但这在 Java 中是不可能的,即使是 1.8。但是,虚拟扩展方法足够相似。草案对它们进行了如下规定: default 子句命名了默认实现,它是一个静态方法。默认实现的签名必须与扩展方法的签名兼容,并将封闭接口的类型作为第一个参数插入。(第 2 节)
    • Java 8 的这个新特性非常漂亮,当然,但它不能回答我的问题 :-( .... 另外,请注意 B 依赖于 A 中的代码。
    猜你喜欢
    • 2019-01-09
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 2016-08-12
    • 1970-01-01
    • 2014-05-23
    • 2021-08-12
    • 2015-04-29
    相关资源
    最近更新 更多