没有矛盾:class A(x: => Int)
等价于class A(private[this] val x: => Int)
and not class A(private val x: => Int)
。private[this]
将值标记为实例私有,而没有进一步说明的私有修饰符允许从该类的任何实例访问该值。
不幸的是,case class A(private[this] val x: => Int)
也不允许定义 a 。我认为这是因为案例类需要访问其他实例的构造函数值,因为它们实现了该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
's toString
-method 来检查这一点。
编辑:在阅读了 Chris Martin 的评论后: 的实现equals
也会带来一个可能比实现更严重的问题toString
(主要用于调试)和hashCode
(如果你不能采取只会导致更高的碰撞率)参数考虑)。您必须仔细考虑如何实施equals
才有意义。