[Scala] HashMapを拡張する

今日はScalaのHashMapを拡張してみます。
多くのJavaプログラマが不満に思っていると思うのですが、Javaではほとんどのクラスがfinalで定義されていることもあり、既存のクラスを拡張することができませんでした。Scalaの良いところは、既存のライブラリも簡単に拡張できることです。

まず、HashMapを使ってみます。Symbolをキーとして、Intを値に持つHashMapを使ってみます。

scala> var hashMap1 = new HashMap[Symbol, Int]
hashMap1: scala.collection.mutable.HashMap[Symbol,Int] = Map()

scala> hashMap1.put('hoge, 1)
res6: Option[Int] = None

scala> hashMap1.put('foo, 2)
res7: Option[Int] = None

scala> hashMap1
res8: scala.collection.mutable.HashMap[Symbol,Int] = Map('hoge -> 1, 'foo -> 2)

scala> hashMap1.contains('hoge)
res9: Boolean = true

scala> hashMap1.contains("hoge")
<console>:7: error: type mismatch;
 found   : java.lang.String("hoge")
 required: Symbol
       hashMap1.contains("hoge")
                         ^

キーの型をSymbolとStringを間違えてしまいました。Stringでアクセスすると、型が異なるので、評価することができませんでした。StringとSymbolは相互にアクセスできてもいいですね。
ということで、StringでもSymbolでもアクセスできるStringAccessHashMapを作成してみます。

import scala.collection.mutable.HashMap

class StringAccessHashMap[T] extends HashMap[Symbol,T] {
  def put(key: String, elem:T) : Option[T] = { super.put(Symbol(key), elem) }

  def contains(key : String) : Boolean = { super.contains(Symbol(key)) }

  def get(key : String): Option[T] = { super.get(Symbol(key)) }
}

内容は簡単です。キーとしてSymbol型を持つHashMap型を継承し、Stringをキーとしてアクセスするインタフェースを追加しただけです。では実際に使ってみましょう。

scala> var hashMap = new StringAccessHashMap[Int]
hashMap: StringAccessHashMap[Int] = Map()

scala> hashMap.put("hoge", 10)
res0: Option[Int] = None

scala> hashMap.get("hoge")
res1: Option[Int] = Some(10)

scala> hashMap.get('hoge)
res2: Option[Int] = Some(10)

scala> hashMap.contains('hoge)
res3: Boolean = true

scala> hashMap
res4: StringAccessHashMap[Int] = Map('hoge -> 10)

お、これは便利かもしれない。