Scala案例类禁止调用名称参数?
我想实现无限列表:
abstract class MyList[+T] case object MyNil extends MyList[Nothing] case class MyNode[T](h:T,t: => MyList[T]) extends MyList[T] //error: `val' parameters may not be call-by-name 问题是不允许通过名称调用。 我听说这是因为val或var构造函数参数不允许使用call-by-name。例如: class A(val x: =>Int) //error: `val' parameters may not be call-by-name 但矛盾的是,正常的构造函数参数仍然是val,尽管是私有的。例如: class A(x: =>Int) // pass 所以问题: >问题真的是关于val或var? >如果那样。由于调用名称是推迟计算,为什么不能val或var计算(或初始化)被推迟? >如何解决cass类来实现无限列表? 解决方法
没有矛盾:class A(x:=> Int)等同于A类(private [this] val x:=> Int)而不是A类(private val x:=> Int)。 private [this]标记一个值instance-private,而没有进一步规范的private-modifier允许从该类的任何实例访问该值。
不幸的是,也不允许定义一个案例类A(private [this] val x:=> Int)。我认为是因为case类需要访问其他实例的构造函数,因为它们实现了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成员。然而,它至少有一个危险:考虑病毒类如何实现toString;调用每个构造函数的toString方法。这可能(并且在这个例子中)将导致值无限地调用它们的值。您可以通过将t.toString添加到MyNode的toString方法来检查。 编辑:阅读Chris Martin的评论之后:equals的实现也会造成一个比执行toString(主要用于调试)和hashCode更严重的问题(这只会导致更高的碰撞率,如果你可以’ t考虑参数)。你必须仔细考虑如何实现平等是有意义的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |