web-dev-qa-db-ja.com

Scalaコンストラクターパラメーター

プライベートvarコンストラクターパラメーターとval/varのないコンストラクターパラメーターの違いは何ですか?範囲/可視性の点で同じですか?

例:

class Person(private var firstName:String, lastName:String)
23
user2456976

はい、2つの重要な違いがあります。まず簡単な方法です。varまたはvalキーワードのないコンストラクターパラメーターは可変変数ではありません。これらの値はクラスの本体で変更できません。

valキーワードに制限したとしても、private valパラメーターとキーワードなしパラメーターには違いがあります。次のことを考慮してください。

class Person(private val firstName: String, lastName: String)

コンパイルされたクラスをjavap -v Personで見ると、firstNameのフィールドが1つしかないことがわかります。 lastNameは単なるコンストラクターパラメータです。つまり、クラスが初期化された後などにガベージコレクションされる可能性があります。

コンパイラは、初期化後にlastNameの値がいつ必要になるかを知るのに十分賢く、その場合はそのためのフィールドを作成します。次のバリエーションを検討してください。

class Person(private val firstName: String, lastName: String) {
  def fullName = firstName + " " + lastName
}

コンパイラは、後でlastNameの値が必要になる可能性があることを認識でき、javapをもう一度チェックすると、クラスに2つのフィールドがあることがわかります(fullNamevalではなくdefとして定義した場合は、フィールドは1つだけです)。

最後に、class-privateの代わりにfirstNameobject-privateを作成すると、まったく古いキーワードとまったく同じように機能することに注意してください-コンストラクターパラメーターが少ない:

class Person(private[this] val firstName: String, lastName: String)

これは、varの代わりにvalでも機能します。

class Person(private[this] var firstName: String, lastName: String)

これらのクラスは両方ともフィールドを持ちません。オブジェクトプライベートアクセスの詳細については、 言語仕様 のセクション5.2を参照してください。

28
Travis Brown

補足として、クラスがケースクラスの場合、すべてのコンストラクターパラメーターは自動的にパブリックフィールドになります。

コンパイラは、privateキーワードが存在する場合は文句を言います。val/ varのないパラメータの場合、defで使用されているかどうかに関係なく、パブリックフィールドが生成されます。

1
Ambling