相互引用的不可变实例 [英] Immutable instances that reference one another

查看:41
本文介绍了相互引用的不可变实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

写下这些类后,有什么可能的方法来创建一对男女朋友吗?也就是男孩有女朋友,男孩也是她男朋友.

With these classes as written, is there any possible way to create a boyfriend/girlfriend pair? That is, a boy with a girlfriend and the boy is also her boyfriend.

abstract class Person(val name: String)

case class Girl(name2: String, val boyfriend: Boy) extends Person(name2)

case class Boy(name2: String, val girlfriend: Girl) extends Person(name2)


object Run extends App {
    val alice: Girl = Girl("alice", Boy("Bob",alice))

    // alice.boyfriend.girlfriend is null, not correct
}

推荐答案

没有惰性求值就不可能制作自引用的不可变结构.然而,Scala 中的惰性求值(用惰性 val 和按名称调用参数表示)并不像 Haskell 中那样普遍,并且它有其局限性.您的代码可以这样重写:

It is impossible to make self-referential immutable structures without lazy evaluation. However, lazy evaluation in Scala (represented with lazy vals and call-by-name parameters) is not so pervasive as, say, in Haskell, and it has its limitations. Your code can be rewritten like this:

Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :paste
// Entering paste mode (ctrl-D to finish)

abstract class Person(val name: String)

class Girl(val name2: String, _boyfriend: => Boy) extends Person(name2) {
    lazy val boyfriend = _boyfriend
}

class Boy(val name2: String, _girlfriend: => Girl) extends Person(name2) {
    lazy val girlfriend = _girlfriend
}


object Run {
    val alice: Girl = new Girl("alice", new Boy("Bob", alice))
}

// Exiting paste mode, now interpreting.

defined class Person
defined class Girl
defined class Boy
defined module Run

scala> Run.alice.name
res0: String = alice

scala> Run.alice.boyfriend.name
res1: String = Bob

scala> Run.alice.boyfriend.girlfriend.name
res2: String = alice

scala>

你看,这里没有案例类——你不能让案例类参数按名称调用,因为它们被公开为 val,并且 val 具有按名称调用类型是没有意义的.此外,我还必须创建额外的惰性 val 字段,以免过早评估按名称调用参数.

You see, no case classes here - you cannot make case class parameters call-by-name since they are exposed as vals, and it does not make sense for vals to have call-by-name type. Also I had to create additional lazy val field so that call-by-name parameter won't be evaluated too early.

这段代码有可能可以简化,但这是我能想到的最简单的方法来实现你想要的.

It is possible that this code can be simplified, but it is the simplest way to achieve what you want I can think of.

这篇关于相互引用的不可变实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆