【问题标题】:Java/Scala Bounded Generics and type inference mismatchJava/Scala 有界泛型和类型推断不匹配
【发布时间】:2015-12-31 21:34:12
【问题描述】:

来自 Java 背景,我知道这不会编译。

public static class SuperClass {}
public static class SubClass extends SuperClass {}

public static <T, U extends T> U returnSub(T sup, U sub) {
    return sub;
}

public static void main(String[] args) {
    SuperClass parent = new SuperClass();
    SubClass child = new SubClass();

    returnSub(parent, child);
    returnSub(child, parent); // Java doesn't like that
}

最后一行会产生编译器错误(编辑:至少在 jdk1.6.0_65 上):

绑定不匹配:Test 类型的泛型方法 returnSub(T, U) 不适用于参数(Test.SubClass、Test.SuperClass)。推断的类型 Test.SuperClass 不是有界参数的有效替代品

所以,我很惊讶,这似乎在 Scala 中工作。我写了下面的示例代码(据我所知,它表达了相同的“逻辑”):

class SuperClass
class SubClass extends SuperClass

def returnSub[Type, SubType <: Type](supArg: Type, subArg: SubType): SubType = {
  subArg
}

override def main(args: Array[String]): Unit = {
  val parent = new SuperClass()
  val child = new SubClass()

  val iAmOkWithThat: SubClass = returnSub(parent, child)
  val iDontGetThat: SuperClass = returnSub(child, parent)
}

Scala 编译器足够聪明,可以说“好的,childSubClass 的一个实例,但是如果我这么说我就不能调用returnSub,所以让如果我将child 视为SuperClass 实例,我会尝试,而且,它可以工作,所以让我们这样做”。

这是怎么回事(如果是的话,你能指出一个关于那个的语言规范)吗?或者也许我的 Scala “转换”不等同于我的 Java 代码?

谢谢!

【问题讨论】:

  • 它应该适用于 Java 和 Scala,因为 TU 都可以是 SuperClass。我尝试了你的 Java 程序,它使用 jdk1.8.0_25 编译并运行得很好。是什么让您认为 Java 不喜欢它?
  • 我那里只有一个旧的 Java。这也许是原因(jdk 1.6.0_65)。编辑以反映这一点。
  • 自 1.6 以来,类型推断有了很大改进。您应该通过 ThisClass.&lt;SuperClass, SuperClass&gt;returnSub(child, parent); 使其适用于 Java 1.5 以后的所有版本。
  • 在同一个 JDK 上运行,scala 编译器 (2.11.7) 不需要额外的推理信息。尽管如此,您的建议确实有效,并使 1.6 javac “快乐”。感谢您指出这一点。随意编辑这个作为答案。

标签: java scala generics


【解决方案1】:

您的代码应该适用于两种语言,因为TU 都可以是SuperClass。使用 Java 1.8,您的代码可以毫无问题地编译。自从引入泛型以来,类型推断有了很大的改进,但是您可以通过编写使其适用于从 1.5 开始的所有 Java 版本

ThisClass.<SuperClass, SuperClass>returnSub(child, parent);

您现在需要提供这样的显式类型参数的频率要少得多了。

至于为什么你在 Scala 上没有遇到同样的问题,恐怕我无法回答,因为我根本不了解 Scala。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 2013-12-21
    • 1970-01-01
    • 2015-04-09
    相关资源
    最近更新 更多