我在scala中遇到以下层次结构的问题:
class ScalaGenericTest {
def getValue[A, B <: Abstract[A]](clazz: B): A = clazz.a
def call: String = {
val sub: Subclass = new Subclass
getValue(sub)
}
}
class Subclass extends Abstract[String] {
def a: String = "STRING"
}
abstract class Abstract[A] {
def a: A
}
Run Code Online (Sandbox Code Playgroud)
编译器似乎无法在对getValue函数的调用中绑定泛型参数A - 我认为它应该能够从Subclass的定义中推断出这一点.编译错误如下:
推断类型参数[Nothing,Subclass]不符合方法getValue的类型参数bounds [A,B <:Abstract [A]]
如果我明确地将泛型类型参数传递给方法,它可以工作,getValue[String,Subclass](sub)但是肯定编译器应该能够推断出这个吗?
相同的层次结构在Java中运行良好:
public class JavaGenericTest {
public <T,U extends Abstract<T>> T getValue(U subclass) {
return subclass.getT();
}
public String call(){
Subclass sub = new Subclass();
return getValue(sub);
}
private static class Subclass extends Abstract<String> {
String getT(){
return "STRING";
}
}
private static abstract class Abstract<T> {
abstract T getT();
}
}
Run Code Online (Sandbox Code Playgroud)
我对Scala很新,所以我可能会遗漏一些微妙之处.
在此先感谢您的帮助!
这是Scala类型推断的一个限制.该问题在SI-2272中描述(该示例使用了implicits,但在明确使用时会出现相同的错误).它已被关闭,因为无法修复.
在这个问题上,Adriaan Moors建议避免双方都有类型变量的约束.即.B <: Abstract[A].一个简单的解决方法是完全避免第二类参数.
def getValue[A](clazz: Abstract[A]): A = clazz.a
scala> val sub = new Subclass
sub: Subclass = Subclass@585cbda6
scala> getValue(sub)
res11: String = STRING
Run Code Online (Sandbox Code Playgroud)
此外,Adriaan还提供了一种使用隐式<:<作为另一种解决方法的方法.将它放在您的示例的上下文中,它看起来像:
def getValue[A, B](b: B)(implicit ev: B <:< Abstract[A]): B = b.a
Run Code Online (Sandbox Code Playgroud)
其中一个实例<:<是通过Predef隐式提供的.
| 归档时间: |
|
| 查看次数: |
731 次 |
| 最近记录: |