Magnolia Tech

いつもコードのことばかり考えている人のために。

Scalaで、既存のクラスに新しい振る舞いを追加する

Rubyにはrefinementsという仕組みが有って、特定のスコープ内だけで既存クラスのメソッドの振る舞いを変えたり、追加したりできます。

例えばStringクラスに、toBlahという、文字列の前に"Blah!"という文字列を追加するというメソッドが欲しくなったとしましょう(そんなシチュエーションは無いと思いますが)。そんな時はこんなコードで実現できます。

module BlahString
  refine String do
    def toBlah
      "Blah " + to_s
    end
  end
end

class UninterestingMessage
  using BlahString

  def make_message(string)
    string.toBlah
  end
end

puts UninterestingMessage.new.make_message("Wolrd!")
# => Blah! Wolrd!

元々、Rubyオープンクラスという仕組みが有って、自由に後からクラスの挙動を変えることができるのですが、影響がグローバルなので、このような影響範囲を限定する仕組みが後から(Ruby 2.1から)導入されました。

Scalaにおける実現方法…implicit class

Scalaにおいても既存のクラスにメソッドを追加するimplicit classという仕組みが有ります。

scala> implicit class BlahString(val string: String) {
     | def toBlah = "Blah " + string
     | }
defined class BlahString

scala> "World!".toBlah
res0: String = Blah World!