当有一个带有类型参数的case类时,我看不出如何调用tupled
方法。似乎可以找到apply
和unapply
。
scala> case class Foo[T](x:T, y:T)
defined class Foo
scala> Foo.apply[Int] _
res1: (Int, Int) => Foo[Int] = <function2>
scala> Foo.unapply[Int] _
res2: Foo[Int] => Option[(Int, Int)] = <function1>
scala> Foo.tupled[Int] _
<console>:10: error: value tupled is not a member of object Foo
Foo.tupled[Int] _
^
对于发生了什么有任何想法?
答案 0 :(得分:15)
案例类的伴随对象在具有类型参数时无法扩展FunctionN
(定义{{1}},tupled
&gt; = 2)。使用
N
当你有一个像
这样的香草类时(Foo[Int] _).tupled
它的构造函数实际上是case class Bar(x: Int, y: Int)
,因此当编译器生成伴随对象Function2[Int, Int, Bar]
时,它可以方便地扩展Bar
。
生成的代码将是
Function2
现在考虑
class Bar extends AnyRef with Product with Serializable { ... }
object Bar extends Function2[Int, Int, Bar] with Serializable { ... }
如果你尝试应用同样的技巧,你很快就会遇到麻烦:
case class Foo[T](x: T, y: T)
由于// this can't compile, what's T?
object Foo extends Function2[T, T, Bar] with Serializable { ... }
未知,编译器无法使T
成为Foo
的子类,并且它不能比扩展Function2
做得更好:< / p>
AnyRef
以上是上面讨论的内容的快速证明(使用class Foo[T] extends AnyRef with Product with Serializable { ... }
object Foo extends AnyRef with Serializable { ... }
):
scala -Xprint:typer
要进行包装,当您有类型参数时,您必须首先获得scala> case class Bar(x: Int, y: Int)
...
<synthetic> object Bar extends scala.runtime.AbstractFunction2[Int,Int,Bar] with Serializable {
...
scala> case class Foo[T](x: T, y: T)
...
<synthetic> object Foo extends AnyRef with Serializable {
...
Function2
然后你可以打电话给val f: Function2[Int, Int, Foo] = Foo[Int] _
tupled