Pitfall 1:protected staticなメンバに要注意

ScalaからJavaのメソッドを読んだり、ScakaのクラスのスーパークラスとしてJavaのクラスを指定することは一般には問題ありませんが、スーパークラス(Java)がprotected staticなメンバを持っていた場合、注意が必要です。

たとえば、次のような

Java:

public class Super { protected static int value = 100; }

Scala:

class Sub extends Super { def foo { println(value) //エラー } }

コードはコンパイルエラーになります。何故でしょうか。

まず、それにはScalaにはstaticなメンバという概念自体が存在しない事を理解する必要があります。もちろん、staticなメンバが存在しないからといってJavaクラスのstaticメンバを参照できないのでは不便ですから、Javaクラスのstaticなメンバは、そのクラスのコンパニオンオブジェクトのメソッドのように扱われます。つまり、Javaクラスを継承するとき、staticなメンバは継承されない事になり、サブクラス側からは、クラス名を省略してスーパークラスのstaticメンバを参照することはできません。そのため、スーパークラスのクラス名を明示的に指定してstaticなメンバを参照する必要があるのですが、Javaのprotected staticなメンバは、サブクラスまたは同一パッケージからのみ参照可能なので、ScalaのクラスからJavaで書かれたスーパークラスのprotected staticなメンバを参照することはできません。

この問題は根本的なものであり、Scala側から直接回避する方法は存在しません。この問題をとりあえず回避するには、Java側でprotected staticなメンバを持つクラスのラッパクラスを作ってあげる必要があります。

たとえば、上記の問題に関しては、次のようなJavaのラッパが必要になるでしょう。

public class SuperWrapper extends Super { public static int getValue() { return value; } public static void setValue(int newValue) { value = newValue; } }