沒有矛盾:class A(x: => Int)
相當於class A(private[this] val x: => Int)
而不是class A(private val x: => Int)
。 private[this]
標記值爲instance-private,而沒有進一步規範的private-modifier允許從該類的任何實例訪問值。
不幸的是,定義case class A(private[this] val x: => Int)
也是不允許的。我認爲這是因爲case-classes需要訪問其他實例的構造函數值,因爲它們實現了equals
方法。
不過,你可以實現一個案例類將手動提供的功能:
abstract class MyList[+T]
class MyNode[T](val h: T, t: => MyList[T]) extends MyList[T]{
def getT = t // we need to be able to access t
/* EDIT: Actually, this will also lead to an infinite recursion
override def equals(other: Any): Boolean = other match{
case MyNode(i, y) if (getT == y) && (h == i) => true
case _ => false
}*/
override def hashCode = h.hashCode
override def toString = "MyNode[" + h + "]"
}
object MyNode {
def apply[T](h: T, t: => MyList[T]) = new MyNode(h, t)
def unapply[T](n: MyNode[T]) = Some(n.h -> n.getT)
}
要檢查這個代碼,你可以嘗試:
def main(args: Array[String]): Unit = {
lazy val first: MyNode[String] = MyNode("hello", second)
lazy val second: MyNode[String] = MyNode("world", first)
println(first)
println(second)
first match {
case MyNode("hello", s) => println("the second node is " + s)
case _ => println("false")
}
}
不幸的是,我不知道肯定爲什麼禁止使用名爲val和var的成員。然而,它至少有一個危險:想想case-classes如何實現toString
;調用每個構造函數值的toString
- 方法。這可以(並且在這個例子中)導致價值無限地自我調節。您可以通過將t.toString
添加到MyNode
的toString
-方法來檢查。
編輯:的equals
的實施也將帶來一個問題,即可能比的toString
的實現(主要用於調試)和hashCode
(這隻會導致更高的更嚴重:閱讀克里斯·馬丁的評論後碰撞率如果你不能把這個參數考慮在內)。你必須仔細考慮如何實現equals
是有意義的。
對於無限數據結構,案例類糖提供什麼價值? 'equals','hashCode','toString'不起作用。而且我不確定我對'unapply'的期望。 – 2014-11-05 04:54:11