2

次の2つのクラスがあるとします。

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

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

ここで、mainメソッドで、次のように2つのクラスをインスタンス化します。

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

主な方法では、インスタンス化する前に家族を入力できます。モデルにこれが欲しいです。しかし、私がメンバーを作成する前にメンバーに入ると、私が書きに行くとき:

println(F1.members)

Set(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を使用すると、クラスを混合順序でインスタンス化できます。たとえば、コンポーネントを作成してから、このコンポーネントにいくつかのタイプを追加します。次に、コンポーネントに追加したタイプを作成します。主な方法で私はそれを行うことができます。メインの最後のステートメントとして、検証を行います。検証を開始するときに、コンポーネントを入力しても何も見つかりません。これらは後でインスタンス化されるためです。この問題は、怠惰なメインでのみ解決できますか?または、ドメインレベルでの解決策はありますか。

4

2 に答える 2

7

使用できます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.

タイプ セーフなビルダー パターンを使用できます。

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()
                                             ^
于 2012-12-07T11:07:00.493 に答える
0

person 変数を遅延させるだけです。

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属性はオンデマンドでのみ評価されます

于 2012-12-07T11:07:02.273 に答える