我正在尝试在 Java 库jOOQ中调用此处set
记录的此方法,并带有签名:
<T> ... set(Field<T> field, T value)
这条 Scala 行是个问题:
.set(table.MODIFIED_BY, userId)
MODIFIED_BY
是一个Field<Integer>
代表表格列。userId
是Int
。有一个从toPredef
的隐式转换,那么为什么不使用它呢?我明白了:Int
Integer
type mismatch; found: org.jooq.TableField[gen.tables.records.DocRecord,Integer]
required: org.jooq.Field[Any]
Note: Integer <: Any
(and org.jooq.TableField[gen.tables.records.DocRecord,Integer] <:
org.jooq.Field[Integer]), but Java-defined trait Field is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10)
更新 - 关于维尼修斯的例子
与其尝试在注释中解释这一点,不如在这里演示当您使用具有协变参数的类型时不会调用隐式转换,例如List[+T]
. 假设我将这段代码放在一个文件中,编译并运行它......
case class Foo(str: String)
object StackOver1 extends App {
implicit def str2Foo(s: String): Foo = {
println("In str2Foo.")
new Foo(s)
}
def test[T](xs: List[T], x: T): List[T] = {
println("test " + x.getClass)
xs
}
val foo1 = new Foo("foo1")
test(List(foo1), "abc")
}
你会看到它调用了 test,但从来没有从String
"abc" 到Foo
. 相反,它选择了 a T
,因为它是和test[T]
之间的公共基类。当您使用它时,它会选择,但它会令人困惑,因为列表中的运行时表示是. 所以看起来它使用了隐式转换,但它没有。您可以通过打开 Scala 提示符来验证...String
Foo
Int
Integer
Any
Int
Integer
scala> :type StackOver1.test(List(new java.lang.Integer(1)), 2)
List[Any]