【问题标题】:java accidential implicit interface implementationjava意外隐式接口实现
【发布时间】:2010-12-23 12:05:07
【问题描述】:

最近遇到了一个有趣的特性,不过,它可能会导致 Eclipse “添加未实现的方法”特性的意外输出。这种“偶尔隐式实现”背后的语言概念的“googl-able”名称是什么?

我不希望下面的代码编译,但它确实并且正在工作

interface CallmeIfc {
  public void callme();
}

class CallmeCode {
  public void callme() {
    // implementation  
  }
}

class CallmeImpl extends CallmeCode implements CallmeIfc {
  // empty class body
}

public static void main(String[] args) {
  CallmeIfc me = (CallmeIfc) new CallmeImpl();
  me.callme(); // calls CallmeCode.callme()
}

【问题讨论】:

  • 嗯...继承?虚函数表?
  • 您的CallMeImpl 通过从CallMeCode 继承来实现public void callme()。就是这样,没有什么特别的名字。
  • @Joonas Pulakka - 我得到了它的名字,“分包”,Impl 就像一个代理,由承包商(超级类)为客户(接口)提供服务,而不让他们彼此认识: )
  • @OrangeDog - 是的,没错,但被滥用了
  • @bobah - 不是真的,这就是它的设计目的。

标签: java inheritance compiler-construction polymorphism


【解决方案1】:

在 CallmeImpl 中,公共 callme() 方法继承自 CallmeCode,因此 CallmeImpl 尊重 CallmeIfc 中定义的协定。

然后,在您的 main() 方法中,多态性允许您将子类实例 (CallmeImpl) 分配给超类或超接口引用 - 在这种特殊情况下,是 CallmeIfc 类型的“我”引用(这里有一个错字,顺便说一句)。

【讨论】:

  • 你回答了我问题的哪一部分?
  • 好吧,我看不到您在此代码及其行为中发现的“意外”内容。这是非常标准的面向对象设计。所以我试图解释使它起作用的OO概念。这里的“googleable 术语”是继承和多态。如果您有更准确的问题,我很乐意为您解答。
  • 我不确定接口和实现代码不在继承树中的同一根叶路径上是“非常标准的 OO 设计”。当我创建一个问题时,我希望得到一个类似“啊!这很简单,它被称为 xxx,像 yyy 一样工作,这就是为什么它在 Java 中不像 C++”这样的答案。
  • 啊,我明白了。看起来 C++ 实现是对 Java 支持的更一般的 OO 的限制,其中可以在不同包中的类/接口之间发生继承。
【解决方案2】:

实际上,这在我看来像是一个编译器错误:Java 语言规范writes

一个实例方法m1 声明在一个 C 类覆盖另一个实例 方法,m2,在类 A 中声明 以下都是正确的:

  • CA 的子类。
  • m1 的签名是m2 签名的子签名(第 8.4.2 节)。
  • 要么
    • m2 是公共的、受保护的或在与 C 相同的包中声明为具有默认访问权限,或者
    • m1 覆盖了一个方法 m3m3 不同于 m1m3 不同于 m2,因此 m3 覆盖 m2

在您的情况下,不满足第一个条件:方法 callme 在类 CallMeCode 中声明,它不是 CallmeIfc 的子类型。

编辑:Bobah 是对的,规范区分了实现和覆盖。事实上,它实际上mandates观察到的行为:

除非声明的类是 摘要,所有的声明 每个直接的方法成员 必须实现超接口 通过此类中的声明 或通过现有的方法声明 从直接超类继承, 因为一个非抽象的类 不允许有摘要 方法

规范没有解释原因。

【讨论】:

  • 我不完全确定实现接口的类是否是该接口的“子类”并且接口方法的实现是否是“覆盖”。所以我们观察到的可能是一个有效的编译器行为,虽然有点不寻常。
【解决方案3】:

虽然 CallmeCode 类没有实现 CallmeIfc 接口,但它提供了必要的实现。就好像 CallmeCode 类实现了该接口。它也适用于这段代码:

interface CallmeIfc {
    public void callme();
}

class CallmeCode implements CallmeIfc {
    public void callme() {
      // implementation  
    }
}

class CallmeImpl extends CallmeCode implements CallmeIfc {
   // empty class body
}

在您的情况下,这很好,因为 CallmeCode 类有一个方法 callme。如果该方法被命名为不同的,它将无法编译。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    相关资源
    最近更新 更多