<< 2008/08/09 | Home | 2008/08/11 >>
PR: 転職    転職    合宿免許    漫画    シルバー    ブライダルエステ    墓地・霊園    葬式   

Scalaのenumは直列化できない?

Valueがインナークラスだというのが、かなりつらいな。Value自体は直列化可能じゃないから、デフォルトコンストラクタが必要だけど、Valueはインナークラスだから、エンクロージングクラスを引数とした、コンストラクタしか用意されていない。う〜む、とりあえずenumは、Javaで用意かなぁ。

Scalaのenum

Scalaでは、enumはどうするんだろうと思っていたんだけど、ちゃんとscala.Enumerationというクラスが用意されていた。いや名前から、java.util.Enumerationみたいなもんだと思って見落としていたんだけど。Scalaなんだから、そんな後方互換性は不要だよな。

Enumerationは、Valueというインナクラスで、メンバを表現する。つまりenum自体と、その中に定義される定数とは、別のクラスになっている。

object Const extends Enumeration {
  def ONE, TWO = Value
}

みたいにして使う。このValueは、インナクラスのValueなのではなくて、Enumeration内に定義されたメソッドだ。

  protected final def Value: Value =
    new Val(nextId, if (nextName.hasNext) nextName.next else null)

で、戻り型は、インナクラスのValueだ。あぁややこしい。で、このValueクラスを見てみると、

  abstract class Value extends Ordered[Value] {
    /** the id and bit location of this enumeration value */
    def id: Int
    override def compare(that: Value): Int = this.id - that.id
    override def equals(other : Any) : Boolean = 
      other match { case that : Value => compare(that) == 0
                    case _ => false } 
    override def hashCode : Int = id.hashCode
...

idが一致すればokなのか。ってそれじゃ、無関係のenum同士がequalになってしまうのでは?

object Const1 extends Enumeration {
  val ONE, TWO = Value
}

object Const2 extends Enumeration {
  val ONE, TWO = Value
}

object Main {
  def main(args: Array[String]) {
    System.out.println(Const1.ONE == Const2.ONE)
  }
}
shanai@shanai-desktop:/tmp$ scala -cp . Main
false

あれ? 平気だ。こんなコードを試しに作ってみると、

class Base {
  class Value {
    def c(v: Value) {}
  }
}

class Foo1 extends Base {
  val ONE = new Value
}

class Foo2 extends Base {
  val ONE = new Value
}

object Main {
  def main(args: Array[String]) {
    val foo1 = new Foo1
    val foo2 = new Foo2

    System.out.println(foo1.ONE.c(foo2.ONE))
  }
}
shanai@shanai-desktop:/tmp$ fsc test2.scala
/tmp/test2.scala:20: error: type mismatch;
 found   : foo2.Value
 required: foo1.Value
    System.out.println(foo1.ONE.c(foo2.ONE))
                                       ^
one error found

あぁ、これがパス依存型というやつか。ValueはBaseクラスにしかないけど、インスタンスによって、別のクラスだと認識されるんだね。このあたりは、Javaから来ると、かなり混乱するな。でもインナクラスのインスタンスってエンクロージングクラスのインスタンスを含んでるわけだから、むしろ、こっちの方が自然な気もしてきた。

このサイトの掲載内容は私自身の見解であり、必ずしもIBMの立場、戦略、意見を代表するものではありません。
日本アイ・ビー・エム 花井 志生 Since 1997.6.8