Javaみたく明示的にアクセスメソッドを定義する必要はないようです。素敵ですね。
パターン1:publicなvarフィールドを定義した場合
このように、publicなvarフィールドを定義するとコンパイル時に自動的にアクセスメソッドを出力してくれます。class Hoge {
var hoge1: String = _
var hoge2: Int = _
}
自動で生成されたアクセスメソッドを呼び出すには、フィールドに直接アクセスするようにしてあげればよいです。val hoge = new Hoge hoge.hoge1 = "hoge" // hoge1に値を設定 hoge.hoge2 = 1 // hoge2に値を設定 println(hoge.hoge1) // hoge1の値を取得 println(hoge.hoge2) // hoge2の値を取得
コンパイル後に出力されたクラスファイルをjadって見てみると、こんなルールになっているのがわかる。
- varなフィールドはprivateになっている。
- setterは、プロパティ名 + "_="になっている。
=は、コンパイル時にJavaで認識できる文字に置き換えられるので「$eq」となっている。 - getterは、プロパティ名になっている。
//***********************************************
// Hogeクラス
//***********************************************
public class Hoge
implements ScalaObject
{
// hoge1のgetter
public String hoge1()
{
return hoge1;
}
// hoge1のsetter
public void hoge1_$eq(String s)
{
hoge1 = s;
}
// hoge2のgetter
public int hoge2()
{
return hoge2;
}
// hoge2のsetter
public void hoge2_$eq(int i)
{
hoge2 = i;
}
public Hoge()
{
}
// 公開フィールドは、privateなフィールドとなっている。
private String hoge1;
private int hoge2;
}
//***********************************************
// アクセスメソッドを呼び出すコード
//***********************************************
Hoge hoge = new Hoge();
// setter(プロパティ名 + "_=")を呼び出すコードに変換されているのがわかる。
hoge.hoge1_$eq("hoge");
hoge.hoge2_$eq(1);
Predef$.MODULE$.println(hoge.hoge1());
Predef$.MODULE$.println(BoxesRunTime.boxToInteger(hoge.hoge2()));
ちなみち、varフィールドをprivateにするとアクセスメソッドが生成されないのでこんな感じにコンパイルエラーが出る。 Error:Error:line (6)error: variable hoge1 in class Hoge cannot be accessed in Hoge
hoge.hoge1 = "hoge"
Error:Error:line (7)error: variable hoge2 in class Hoge cannot be accessed in Hoge
hoge.hoge2 = 1
Error:Error:line (9)error: variable hoge1 in class Hoge cannot be accessed in Hoge
println(hoge.hoge1)
Error:Error:line (10)error: variable hoge2 in class Hoge cannot be accessed in Hoge
println(hoge.hoge2)
パターン2:明示的にアクセスメソッドを定義する方法
明示的にアクセスメソッドを定義するには、フィールドをprivateにしてあげてパターン1で自動生成された形式でsetterとgetterを宣言してあげればよいです。例えば、アクセスメソッドで処理をしたい場合やgetterのみを宣言する場合に使います。(Javaのように、getHogeやsetHogeを宣言する必要はないです。)
気をつけないといけないのは、フィールド名とgetter名が同じになってはいけないのと、
setter名は、プロパティ名の後に「_=」をつけるのを忘れないこと。「_」と「=」の間にスペース入れちゃうのもダメ。
// フィールドはprivateで宣言する。
private var h1: String = _
private var h2: Int = _
// getter
def hoge1: String = h1
// setter
def hoge2_=(hoge2: Int) {
require(hoge2 > 100)
h2 = hoge2;
}
// getter
def hoge2: Int = h2