部分的に構築されたオブジェクトをそのままにしておくことは、Scala では一般的に理想的な方法ではありません。通常、オブジェクトがインスタンス化される方法を再考して、壊れにくい別のパターンを使用できないかどうかを確認します。たとえば、メソッドで初期化されていない変数を設定する代わりに、次のようにします。
class Foo { var a: String = null; var b: String = null }
def initFooA(s: String, f: Foo) { if (f.a == null) f.a = s }
def initFooB(s: String, f: Foo) { if (f.b == null) f.b = s }
f
initFooA("salmon", f)
// Do stuff
initFooB("herring", f)
コードを再構築して必要な値をオンデマンドで生成しようとし、それまで foo のインスタンス化を遅らせます。
case class Bar(a: String, b: String) {}
def initBarA(s: String) = s
def initBarB(s: String) = s
val iba = initBarA("halibut")
// Do stuff
val ibb = initBarB("cod")
Bar(iba, ibb)
Scala はタプル (および型推論) に簡単にアクセスできるため、これは Java よりもはるかに簡単です。
あなたができるもう一つのことは、遅い初期化を他の人に任せることです。
case class Baz(a: String)(bMaker: => String) {
lazy val b = bMaker
}
ここで、パラメータ b を作成する何かを渡し、処理が必要な後期初期化処理を処理するように手配します。これは常に vars を設定する必要を回避するわけではありませんが、クラス コードから初期化ロジックにプッシュするのに役立ちます (通常は、変数を設定するのに適した場所です)。
これを vars で行うのは少し簡単ではありません。現実的には、クラスをそれに専念させるのがおそらく最善の方法です。たとえば、次のようにします。
class LazyVar[A](initial: => A) {
private[this] var loaded = false
private[this] var variable: A = _
def apply() = { if (!loaded) { loaded = true; variable = initial }; variable }
def update(a: A) { loaded = true; variable = a }
}
次に、(悲しいことに)()
読み取りと書き込みのたびに使用する必要があります。
scala> val lv = new LazyVar({ println("Hi!"); 5 })
lv: LazyVar[Int] = LazyVar@2626ea08
scala> lv()
Hi!
res2: Int = 5
scala> lv() = 7
scala> lv()
res4: Int = 7
次に、実際のクラスの代わりにこのクラスのインスタンスを使用var
し、遅延初期化子を渡します。(lazy val
内部はこれと非常によく似ています。コンパイラは、ユーザーが気付かないように保護しているだけです。)
最後に、時々値が欠落している完全に機能するオブジェクトが必要な場合var x: Option[X]
は、使用したい構造です。標準の Java 作成パターンを回避する方法が見つからない場合 (そして、パフォーマンスが重要であり、それを行う余裕がないため、より多くの情報を使用して相互に作成するオブジェクトのような、より風変わりなものを試したくない場合) 、または型チェックでオブジェクトが適切に作成されていることを確認できるようにするためにボイラープレートをそれほど多く書くのは嫌いですが、それ以外の場合はそれを使用したいので、var x: X = null
私はそれを選択し、 ではありません_
。がプリミティブである場合X
は、とにかく適切な値を賢明に選択する必要があります (たとえば、 for ではなくの代わりDouble.NaN
に0.0
-1
0
Int
) は、私が初期化されていないことを示します。それが一般的なコードであり、 の代わりに が必要な場合は、Any
との間を-ing で行ったり来たりすることが、型チェックが不十分な状況から抜け出すためのおそらく最良の方法です (実際には を使用できないと仮定すると、その時点でより明確になります)。AnyRef
asInstanceOf
Any
AnyRef
Option