加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala案例类禁止调用名称参数?

发布时间:2020-12-16 09:32:16 所属栏目:安全 来源:网络整理
导读:我想实现无限列表: 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或
我想实现无限列表:

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考虑参数)。你必须仔细考虑如何实现平等是有意义的。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读