2011-09-07 40 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