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

Scala:使用稍后创建的实例初始化字段,scala,initialization,field,Scala,Initialization,Field,假设我有两个类: 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 Perso

假设我有两个类:

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允许我以混合顺序实例化类。例如,我创建一个组件,然后向该组件添加一些类型。然后我创建已添加到组件的类型。主要的方法是我能做到。作为最后一句话的主要我把验证。 开始验证时, 组件中的类型找不到任何内容,因为这些内容稍后会实例化。这个问题只能用懒惰来解决吗?
或者在域级别有解决方案。

您可以使用
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>:粘贴
//进入粘贴模式(按ctrl-D键完成)
案例类人员(val名称:String,val姓氏:String)
案例类系列(val名称系列:字符串,val成员:集合[Person])
lazy val f1=新族(“红色”,集合(p1,p2))
lazy val p1=新人(“约翰”、“史密斯”)
lazy val p2=新人(“路易斯”、“史密斯”)
//正在退出粘贴模式,现在正在解释。
限定类人
定义类族
f1:族=
p1:人=
p2:人=
scala>f1
res0:Family=Family(红色,Set(Person(约翰,史密斯),Person(路易斯,史密斯)))
如果只想在创建对象后的某个地方设置一次值,则应使用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>") + ")"
}
并发导入。{Promise,Future}
案例类人员(val名称:String,val姓氏:String)
类族(val名称族:字符串){
private val members Promise=Promise[Set[Person]]
def setMembers(m:Set[Person]){membersPromice.success(m)}
val membersFuture=membersPromice.future
def members=membersFuture.value.map(ux.get)
重写def toString()=“家族(“+nameFamily+”,“+members.getOrElse(“+”)”
}
用法:

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.
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>val f=新系列(“红色”)
f:族=族(红色)
scala>val(p1,p2)=(人(“约翰”、“史密斯”)、人(“路易斯”、“史密斯”))
p1:人=人(约翰,史密斯)
p2:人=人(路易斯,史密斯)
scala>f.setMembers(Set(p1,p2))
scala>f
res1:Family=Family(红色,Set(Person(约翰,史密斯),Person(路易斯,史密斯)))
scala>f.setMembers(Set(p1,p2))
java.lang.IllegalStateException:承诺已完成。
您可以使用:

案例类人物(val name:String,val姓氏:String)
案例类系列(val名称系列:字符串,val成员:集合[Person])
密封抽象类TBool
类TTrue扩展了TBool
类TFalse扩展了TBool
类FamilyBuilder[WithName FamilyBuilder(),其成员集(p1,p2)的名称为“Red”create()
res2:Family=Family(红色,Set(Person(约翰,史密斯),Person(路易斯,史密斯)))
scala>FamilyBuilder(),名称为“Red”create()
:1:错误:无法证明TFalse=:=t正确。
名为“Red”的FamilyBuilder()创建()
^

您只需将persons变量设置为惰性变量即可

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

scala> println(F1.members)
Set($line1.$read$$iw$$iw$Person@185623a7, $line1.$read$$iw$$iw$Person@3f3eb56c)

已编辑

您可以在类本身中将族成员定义为懒惰

class Family(val nameFamily: String, memberSet: => Set[Person]) {
    lazy val members= memberSet
}

通过这种方式,
members
属性仅在需要时进行评估

我只能在主要部分使用惰性变量。在类的声明中,有一个解决方案将应用于域的模型中。编辑答案以解决您的问题。我只能在主要部分使用惰性变量。有一个解决方案将应用于模型中关于域的,在类的声明中。您好,谢谢您的回答,但这不是我正在寻找的。我已经更新了我的问题。好的,让我们尝试使用生成器实现您的目标。有用的答案,生成器链接已失效,仅根据您的答案还没有足够的解释。@JMess请参阅更新。您还可以查看这两个答案以了解更多信息其他示例:,我想您可以尝试按名称传递
构造函数参数,如
A(按名称:=>B)
,对于所有域对象,初始化内部
惰性成员。但很难用一般方式说,这取决于域和程序的结构。如果可能的话,创建独立于订单的DSL似乎不是一件容易的任务!
class Family(val nameFamily: String, memberSet: => Set[Person]) {
    lazy val members= memberSet
}