scala - Scala 中案例类的不可变配对实例?

标签 scala

我正在尝试建立一种可以逆转的关系模型。例如,North 的反面可能是 South。左的反面可能是右。我想用一个案例类来表示我的关系。我在这里找到了一个使用案例对象的类似解决方案,但这并不是我想要的,here .

这是我的非功能代码:

case class Relationship(name: String, opposite:Relationship)

def relationshipFactory(nameA:String, nameB:String): Relationship = {
  lazy val x:Relationship = Relationship(nameA, Relationship(nameB, x))
  x
}

val ns = relationshipFactory("North", "South")

ns // North

ns.opposite // South

ns.opposite.opposite // North

ns.opposite.opposite.opposite // South

是否可以更改此代码以便:

  • 不会崩溃
  • 我可以根据需要成对地创建这些东西。

最佳答案

如果你真的想构建具有循环依赖的不可变对象(immutable对象)的图,你必须将 opposite 声明为 def,并且(最好)再向混合:

abstract class Relationship(val name: String) {
  def opposite: Relationship
}

object Relationship {

  /** Factory method */
  def apply(nameA: String, nameB: String): Relationship = {
    lazy val x: Relationship = new Relationship(nameA) {
      lazy val opposite = new Relationship(nameB) {
        def opposite = x
      }
    }

    x
  }

  /** Extractor */
  def unapply(r: Relationship): Option[(String, Relationship)] =
    Some((r.name, r.opposite))

}

val ns = Relationship("North", "South")

println(ns.name)
println(ns.opposite.name)
println(ns.opposite.opposite.name)
println(ns.opposite.opposite.opposite.name)

如果您在这个循环依赖环上运行几百万轮,您可以很快说服自己不会发生任何不好的事情:

// just to demonstrate that it doesn't blow up in any way if you
// call it hundred million times:
// Should be "North"
println((1 to 100000000).foldLeft(ns)((r, _) => r.opposite).name)

它确实打印了“North”。它不适用于案例类,但您始终可以添加自己的提取器,因此它有效:

val Relationship(x, op) = ns
val Relationship(y, original) = op
println(s"Extracted x = $x y = $y")

它为 xy 打印“North”和“South”。


然而,更明显的做法是只保存关系的两个组成部分,并添加 opposite 作为构造相反对的方法。

case class Rel(a: String, b: String) {
  def opposite: Rel = Rel(b, a)
}

实际上,这已经在标准库中实现了:

scala> val rel = ("North", "South")
rel: (String, String) = (North,South)

scala> rel.swap
res0: (String, String) = (South,North)

关于scala - Scala 中案例类的不可变配对实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48973051/

相关文章:

java - Eclipse scala.object 无法解析

scala - 如何记录对http4s客户端的所有请求

scala - 玩转框架+SLICK(Scalaquery)教程

Scala 功能组合

scala - 测试给定实例是否是 Scala 中给定类的(子)类

scala - scala 中具有不同类型参数的 Varargs

scala - 如何使用Scala Spark快速处理数百万个小JSON文件?

java - org.elasticsearch.client.transport.NoNodeAvailableException : None of the configured nodes are available: []

scala - 对于这种情况,如何在 Scala 中使用 "dispatch"HTTP 客户端库?

scala - 变换和展平析取列表