2011-12-15 31 views
5

在「編程Scala中」一書第22章,該::類(缺點)被定義爲使用新使用Scala最後一種情況類

final case class ::[T](hd: T, tl: List[T]) extends List[T] { 
    //... 
} 

::方法在List類被定義爲如下:

def ::[U >: T](x: U): List[U] = new scala.::(x, this) 

爲什麼需要new創建的finalcaseclass ::一個實例?這純粹是爲了消除歧義嗎?

+4

final只表示該類不能被擴展,它與實例創建無關:-)。案例類基本上是一個可以在「匹配案例」塊中進行比較的類。 – aishwarya 2011-12-15 02:32:48

回答

6

有了case類,你會自動獲得一個同伴對象,其apply方法調用構造函數,以同樣的方式,你可以做到這一點與普通類:

class Foo(val value: Int) 
object Foo { def apply(value: Int) = new Foo(value) } 

val x = new Foo(42) // 
val y = Foo(42)  // both work the same 

可以實例case類與new如果您想要。理論上它可能會稍微快一些,因爲它不需要通過伴侶對象的方法apply,但我嘗試了一個快速的基準測試,並且在性能上完全沒有區別,所以我想它是由編譯器優化的,或者只是一個無法估量的小與實際施工相比有差異。

所以我不認爲你給的例子中的new有什麼意義,也可能被遺漏了。

3

你是對的; new不是強制性的。他們可以定義的實例方法List#::這樣也很好:

def ::[U >: T](x: U): List[U] = scala.::(x, this) 

(需要注意的是,我們有:

type :: = collection.immutable.:: 
val :: = collection.immutable.:: 

scala包對象定義;第一個是爲什麼你new scala.::(x, this)作品,第二個是爲什麼我的scala.::(x, this)工作。)

The form the library uses直接調用構造函數,像你的那樣。替代方法調用爲::案例類生成的合成伴隨對象的apply方法,該方法只是簡單地調用構造函數。也許調用構造函數被認爲更清晰或更高效? (效率的提高應該是幾乎爲零,不過,因爲如果編譯器不內聯調用apply,JVM將),我想最緊湊的形式:

def ::[U >: T](x: U) = ::(x, this) 

可能被誤認爲是一些古怪(即不可能)遞歸調用,並且無論如何都模糊了名爲::List方法::的方法之間的區別,Odersky教授爲了最大限度地提高讀者理解力而努力保持分離。

希望這會有所幫助。

相關問題