简体   繁体   English

Java / Scala有界泛型和类型推断不匹配

[英]Java/Scala Bounded Generics and type inference mismatch

Coming from a Java background, I understand that this does not compile. 来自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
}

The last line produces a compiler error (EDIT : at least on jdk1.6.0_65) it does : 最后一行产生编译器错误(编辑:至少在jdk1.6.0_65上),它确实:

Bound mismatch: The generic method returnSub(T, U) of type Test is not applicable for the arguments (Test.SubClass, Test.SuperClass). 绑定不匹配:类型Test的泛型方法returnSub(T,U)不适用于参数(Test.SubClass,Test.SuperClass)。 The inferred type Test.SuperClass is not a valid substitute for the bounded parameter 推断类型Test.SuperClass不是有界参数的有效替代

So, I got surprised, that this seems to work in Scala. 所以,我很惊讶,这似乎在Scala中起作用。 I wrote the sample code below (which as far as I can tell, expresses the same "logic") : 我在下面编写了示例代码(据我所知,表达了相同的“逻辑”):

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

I guess the Scala compiler is smart enough to say "OK, child is an instance of SubClass , but I can't invoke returnSub if I say that, so let me try if I consider child as a SuperClass instance, and, well, it works, so let's do that". Scala编译器很聪明,可以说“好吧, childSubClass一个实例,但是如果我这么说我就不能调用returnSub ,所以如果我把child视为一个SuperClass实例,让我试试吧,好吧,它工作,所以让我们这样做“。

Is that what's going on (and if so, can you point to a language specification about that) ? 这是发生了什么(如果是这样,你能指出一个语言规范)吗? Or maybe my Scala "conversion" is not equivalent to my Java code ? 或者我的Scala“转换”可能不等同于我的Java代码?

Thanks! 谢谢!

Your code should work for both languages because T and U can both be SuperClass . 您的代码应该适用于这两种语言,因为TU都可以是SuperClass With Java 1.8 your code compiles without problems. 使用Java 1.8,您的代码可以毫无问题地编译。 Type inference has improved greatly since generics were introduced, but you can get this to work on all versions of Java from 1.5 onwards by writing 自从引入泛型以来,类型推断已经有了很大的改进,但是你可以通过编写从1.5开始在所有版本的Java上使用它

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

You need to provide explicit type arguments like this much less frequently now. 你现在需要提供这样的显式类型参数。

As for why you don't get the same issues with Scala, I'm afraid I can't answer that as I'm don't know Scala at all. 至于为什么你没有得到与Scala相同的问题,我恐怕无法回答,因为我根本不了解Scala。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM