Scalaにおけるシングルトンオブジェクトの罠
class Sample
{
private object Inner {
private var value : Int = 0
def getValue = value
def addValue = { value += 1 }
}
def addValue = Inner.addValue
def getValue = Inner.getValue
}
object Main {
def main(args: Array[String]): Unit = {
//静的に値がカウントされているのかを実験
val obj = new Sample
obj.addValue
printf( "オブジェクト1の値:%d\n", obj.getValue )
val obj1 = new Sample
obj1.addValue
printf( "オブジェクト2の値:%d\n", obj1.getValue )
}
}
※NetBeansにて試しました。このサンプルを実行すると予想に反して、オブジェクト1と、オブジェクト2の値が共に1になってしまいます。シングルトンオブジェクトなのにこれは変です。これでは、内部オブジェクトにして、静的変数を模倣できません。
その答えは、Scalaの実装方式にあるようです。Scalaは自動生成クラスのインスタンスとして、シングルトンオブジェクトを実装しています。ですから、インナークラスの値が毎回初期化されているように見えるのです。私はてっきり、次の様なJavaプログラムと等価になると思っていました。
//静的内部クラス
class Sample
{
private static class Inner {
private static int value = 0;
static int getValue() { return value; }
static void addValue() { value += 1; }
}
void addValue() { Inner.addValue(); }
int getValue() { return Inner.getValue(); }
}
public class Main {
public static void main( String[] args ) {
//静的内部クラスを検証
Sample obj = new Sample();
obj.addValue();
System.out.printf("オブジェクト1の値:%d\n", obj.getValue() );
Sample obj1 = new Sample();
obj1.addValue();
System.out.printf("オブジェクト2の値:%d\n", obj1.getValue() );
}
}
どうやら、内部オブジェクトに定義して、クラス数の増加を防ぐ方法は採れないようです。とはいえ、これは明らかにおかしな現象だから、後で直されるかもしれません。