これに対する答えは次のとおりです。
オブジェクトのインスタンス化では、'var' の代わりに 'val' が使用されます。
作成されるオブジェクトの各メンバー変数も、'var' ではなく 'val' です。これは、設定後にユーザーがオブジェクト値を更新するのを防ぐためです。
これに対する答えは次のとおりです。
オブジェクトのインスタンス化では、'var' の代わりに 'val' が使用されます。
作成されるオブジェクトの各メンバー変数も、'var' ではなく 'val' です。これは、設定後にユーザーがオブジェクト値を更新するのを防ぐためです。
オブジェクトのユーザーがオブジェクトを変更する方法がない場合、そのオブジェクトは不変です。つまり、メンバー変数を再割り当てしたり、それらの変数によって参照されるオブジェクトを変更したりするパブリックメソッドがあってはなりません。すべてのオブジェクトのメンバーがval
sである場合、これにより前者が保証されます(つまり、再割り当てできません)が、後者は保証されません(つまり、これらの変数によって参照されるオブジェクト自体が変更可能である場合でも、それらのオブジェクトに対して変更メソッドを呼び出すことで変更できます。val
s)によってのみ参照されている場合でも。
また、メンバーがsとして宣言されている場合var
でも、オブジェクトのメソッドのいずれも実際に変数を再割り当てしない(または変数の変更メソッドを呼び出す)場合、オブジェクトは不変である可能性があることに注意してください。もちろん、それらはプライベートであると想定しています。
したがってval
、オブジェクトが不変であるためには、メンバーだけを持つことは必要でも十分でもありません。オブジェクトがaval
またはa var
(または両方)によって参照されているかどうかは、その問題に違いはありません。
@sepp2k は、オブジェクトが技術的に不変であるという基準を適切かつ正確に説明しています。彼の答えに欠けている微妙な点の 1 つは、すべてのメンバー変数が外部から見える状態に対応しているわけではないということです。メンバーは、たとえば、外部から直接見ることができないローカルで計算が難しいデータを格納するためのキャッシュされた内部値である場合もあります (したがってprivate[this]
、Scala のように修飾されます)。オブジェクトはvar
、計算されたハッシュ値を格納するなどのメンバーを持つことができます。アクセサーの動作が純粋に機能的である限り、つまり、同じオブジェクトの呼び出しごとに常に同じ値を生成する限り、パブリック getter を介してアクセスすることもできます (ただし、内部にキャッシュされた値を再利用すると、より速く返されます)。
Scala コンパイラはこの違いを認識しているため、可変状態を内部で使用している場合でも、不変クラスを正しく実装するのに役立ちます。これは、ジェネリック型の差異が発生する場合に重要です。つまり、コンパイラは、クラスにこの型の再割り当て可能なフィールドが含まれていても、ジェネリック型パラメーターが共変であることを許可します。これらのフィールドがprivate[this]
.オブジェクトはで定義されました (これは型エラーを引き起こす分散の前提条件です)。
これについては、 Programming in Scalaのセクション 19.7 で、コード例を使用してより詳細に説明されています。