gpt4 book ai didi

Scala:使用稍后创建的实例初始化字段

转载 作者:行者123 更新时间:2023-12-02 07:38:24 25 4
gpt4 key购买 nike

假设我有这两个类:

class Person (val name: String, val surname: String)

class Family (val nameFamily: String, val members: Set[Person])

现在在main方法中实例化两个类如下:

val F1 = new Family ("Red", Set(P1, P2))
val P1 = new Person ("John", "Smith")
val P2 = new Person ("Luis", "Smith")

main 方法允许我在实例化之前输入家庭成员。我想要这个用于我的模型。但是如果我在他们创建之前输入成员,当我去写:

println(F1.members)

我返回一个集合(null)。

如果你先写主要人物,像这样:

val P1 = new Person ("John", "Smith")
val P2 = new Person ("Luis", "Smith")
val F1 = new Family ("Red", Set(P1, P2))

我没问题。

但我想以任何顺序编写实例,最后运行族验证。

我可以解决这个问题。我的意思是,我可以使用稍后创建的实例来初始化我的字段。

请原谅我糟糕的英文翻译。

上传 #1

我在 Scala 中实现了一个域,我使用 DSL 创建域的实例。我的 DSL 允许我以混合顺序实例化类。例如,我创建一个组件,然后向该组件添加一些类型。然后我创建我添加到组件的类型。在主要方法中我可以做到。作为 main 的最后一条语句,我进行了验证。开始验证时,Component 中的类型没有找到任何东西,因为这些都是稍后实例化的。这个问题只能在 main with lazy 中解决吗?或者是否有域级别的解决方案。

最佳答案

你可以使用lazy val:

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

case class Person (val name: String, val surname: String)
case class Family (val nameFamily: String, val members: Set[Person])

lazy val f1 = new Family ("Red", Set(p1, p2))
lazy val p1 = new Person ("John", "Smith")
lazy val p2 = new Person ("Luis", "Smith")

// Exiting paste mode, now interpreting.

defined class Person
defined class Family
f1: Family = <lazy>
p1: Person = <lazy>
p2: Person = <lazy>

scala> f1
res0: Family = Family(Red,Set(Person(John,Smith), Person(Luis,Smith)))

如果你想在创建对象后的某处设置一些值,你应该使用 scala 2.10 中的 Promise:

import concurrent.{Promise, Future}

case class Person (val name: String, val surname: String)
class Family (val nameFamily: String) {
private val membersPromice = Promise[Set[Person]]
def setMembers(m: Set[Person]) { membersPromice.success(m) }
val membersFuture = membersPromice.future
def members = membersFuture.value.map(_.get)
override def toString() = "Family(" + nameFamily + ", " + members.getOrElse("<future>") + ")"
}

用法:

scala> val f = new Family("red")
f: Family = Family(red, <future>)

scala> val (p1, p2) = (Person("John", "Smith"), Person("Luis", "Smith"))
p1: Person = Person(John,Smith)
p2: Person = Person(Luis,Smith)

scala> f.setMembers(Set(p1, p2))

scala> f
res1: Family = Family(red, Set(Person(John,Smith), Person(Luis,Smith)))

scala> f.setMembers(Set(p1, p2))
java.lang.IllegalStateException: Promise already completed.

您可以使用 type-safe builder pattern :

case class Person (val name: String, val surname: String)
case class Family (val nameFamily: String, val members: Set[Person])

sealed abstract class TBool
class TTrue extends TBool
class TFalse extends TBool
class FamilyBuilder[WithName <: TBool, WithMembers <: TBool](val nameFamily: Option[String], val members: Option[Set[Person]]) {
def withName(nameFamily: String)(implicit i: WithName =:= TFalse) = new FamilyBuilder[TTrue, WithMembers](Some(nameFamily), members)
def withMembers(members: Set[Person])(implicit i: WithMembers =:= TFalse) = new FamilyBuilder[WithName, TTrue](nameFamily, Some(members))
def create()(implicit i1: WithName =:= TTrue, i2: WithMembers =:= TTrue) = Family(nameFamily.get, members.get)
}
object FamilyBuilder {
def apply() = new FamilyBuilder[TFalse, TFalse](None, None)
}

用法:

scala> FamilyBuilder() withName "Red" withMembers Set(p1, p2) create()
res1: Family = Family(Red,Set(Person(John,Smith), Person(Luis,Smith)))

scala> FamilyBuilder() withMembers Set(p1, p2) withName "Red" create()
res2: Family = Family(Red,Set(Person(John,Smith), Person(Luis,Smith)))

scala> FamilyBuilder() withName "Red" create()
<console>:1: error: Cannot prove that TFalse =:= TTrue.
FamilyBuilder() withName "Red" create()
^

关于Scala:使用稍后创建的实例初始化字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13761670/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com