Scala日記

Scalaの備忘録。ときどき研究の話。

基本コンストラクタの引数は他のメソッド内で使わない場合 private field として保持されない

入門書で明示的に教えてくれないシリーズその2。

class A(s:String){
    def i = s.toInt
}

class B(s:String)

class C(s:String){
    val i = s.toInt
}

上のようなコードにおいて、Asが private field として保持されるのはみんな知っているが、BCsが private field として保持されるのかどうかを明示的に記述している文献はなかなか見当たらない。 コップ本の基本コンストラクタの項目には、基本コンストラクタの引数は「必要なら、渡された値でフィールドを初期化し」や「クラス本体で使われないフィールドは保持『しなくてよい』」などと書かれているが、「しなくてよい」という書き方は定義としてはなんとも曖昧で実際の動作が気になる。

本当のところどうなっているのかいろいろ調べたが、文献からは確信が持てずじまいだったので、以前書いた

ym.hatenadiary.jp

で自分で調べてみた。やり方は

scala -Xprint:constructors

として、上のコードを張り付け、コンパイル結果を見る。すると、表題の結論であることが分かる。 ちなみに、同じ研究室の方に調べてもらったところによると、Martin Odasky 曰く、

"(メソッドで使われている場合は private field になり、使われていない場合は基本コンストラクタの処理が終わった時点で捨てられるという推測は) That's all true, but it should be treated as an implementation technique. That's why the spec is silent about it. "

とのこと。つまり、この仕組みは特にScalaの仕様に含まれているわけではないということ。 どのようにプログラミングを行うかという作法に関わる結構重要な決め事のようにも思えるのだが、何を仕様に含めるべきかという理念の違いなのだろうか。

参考:

  1. Scala Reference and Primary Constructor Parameters | The Scala Programming Language