2011-09-07 102 views
12

当我得知案例类扩展Product后,我想知道他们为什么不扩展ProductN。例如,给予相同的代码:为什么案例类仅扩展Product而不扩展Product1,Product2,...,ProductN?

case class Foo(a: Int) 

我期望Foo(1).asInstanceOf[Product1[Int]]工作,但它不会(与斯卡拉2.9.1检查,并通过其他渠道和Product文件确认)。

我感兴趣的是这个,因为我想声明的类,如:

abstract class UnaryOp[T1 <: Exp[_], R](t1: T1) extends Exp[R] { 
    this: Product1[T1] => 
} 

这种方式,对于一个一元操作,必须实现产品1的节点。如果仅仅是一个具有一个参数的案例类就足够了,那将会很好。

+0

我对这里的downvote感到困惑。 downvoter可以解释吗? – Blaisorblade

回答

11

考虑一下:

case class X(n: Int) 
case class Y(x: String, y: Int) extends X(y) 

如果case类扩展ProductN,那么这将延长两个Product1Product2,但类型参数的变化,所以有_1两个不同的重载。这只是一个问题 - 我敢打赌还有其他问题。

现在,案例类继承案例类已被废弃,Martin Odersky现在正在考虑让它们继承ProductN。 AFAIK,尚未完成,但障碍已被删除。

+4

是的,希望这会使它成为未来的Scala版本,因为它允许编写类型安全的案例类的通用分解函数。 –

+1

是否有可能在Scala中继承案例类? – Taky

0

如果Product1[Int]本来会自动延长,那么val _1: Int也必须提供。虽然我可以想象,可以自动将a分配给_1等等,但事实并非如此。可能只是为了不让事情变得更加复杂。

+0

在每个实例中添加'val _1:Int'会浪费内存,但Product1 [T]'有一个抽象定义'def_1:T',并为其添加实现('def_1:T = a')doesn不会改变实例大小。请参阅Daniel C. Sobral的回答! – Blaisorblade

+0

是的,你是对的。我一定忽略了它。 – agilesteel

+1

这里会发生什么?案例类C(_2:String,_1:Int) – nafg

3

马丁说我们可以做到这一点,我马上回来了。它现在还不能正常工作,但是它的确如此,它在主干构建中落后于X实验。

scala> case class Foo[T, U](x1: T, x2: U) 
defined class Foo 

scala> Foo(List("a"), "b") 
res0: Foo[List[java.lang.String],java.lang.String] = Foo(List(a),b) 

scala> res0.isInstanceOf[Product2[_,_]] 
res1: Boolean = true 
+0

谢谢,这真是太棒了 - 这对于下一个Scala版本来说很棒!我不确定接受哪个答案,但为此,我认为我仍然必须接受Daniel C. Sobral的解答。 – Blaisorblade

+0

我在2.10.0-M5中试了一下,结果令人困惑。 _1和_2出现在Foo上,但它不是Product2的子类型,并且这些成员未由Scaladoc记录: '''scala> Foo(List(“a”),“b”) res10:Foo [List [字符串],字符串] =美孚(列表(A),b) 阶> res10.isInstanceOf [产品2 [_,_]] res11:布尔=假 阶> res10._1 res12:列表[字符串] =列表(a) scala> Some(1)._ 1 res13:Int = 1''' – Blaisorblade