目標
Scala の implicit (暗黙的な型変換)があるとどううれしいか紹介する.
implicit の簡単な紹介
型の不一致を解消するための型変換の操作が繰り返し実装に現れると,コードのシンプルさが失われ可読性が落ちる.そこで, implicits を用いることで暗黙的に型の不一致を解消でき,シンプルでわかりやすいコードを記述することができる.さらにこれを応用させて,組み込み型のクラスに対してあたかも新しいメソッドを追加したようにメソッドを呼び出すことができる.
使用例とメリット
異なる複数の通貨間で加算と減算を実行するコードを書く場合を取り上げて, implicit により実装がシンプルになる例を紹介する.ここでは 100 円 + 1 ドル (= 111円) = 211 円 などの演算を想定する.円,ドル,ユーロ,それぞれの貨幣を示すクラス, Yen, Dollar, Euro を定義し,それぞれに加算を実行する add メソッドと減算を実行する sub メソッドを定義する.同じ通貨の間での加算や減算の結果は自明に定義できるが,異なる通貨との演算は自明に定義できない.とりわけ,そのときの為替レートに応じて演算結果が変化するため,演算の対象のクラスに応じて場合分けの実装が必要になる.すると各クラス,各演算ごとに場合分けが頻出し,実装は複雑になる.
そこで,implicit を用いることで実装がシンプルになる.各通貨クラスの add, sub メソッドの引数は,自クラスのみを受け付けるように実装する.implicit により, Yen <-> Dollar <-> Euro 間の変換を暗黙的に実行できるようにすることで,場合分けを必要とせずに異なる通貨間の演算が記述できるようになる.以下にソースコードを記述する.
// Yen と Dollar と Euro 間を暗黙的に型変換するメソッド
object ImplicitFunctions {
implicit def dollar2yen(dollar:Dollar):Yen = new Yen(dollar.dollar * 111)
implicit def euro2yen(euro:Euro):Yen = new Yen(euro.euro * 128)
implicit def yen2dollar(yen:Yen):Dollar = new Dollar(yen.yen * 0.009)
implicit def euro2dollar(euro:Euro):Dollar = new Dollar(euro.euro * 1.16)
implicit def yen2euro(yen:Yen):Euro = new Euro(yen.yen * 0.0078)
implicit def dollar2euro(dollar:Dollar):Euro = new Euro(dollar.dollar * 0.86)
}
// 以下通貨のクラス.各通貨は自身の通貨としか
// 加減演算できないような定義である.
case class Yen (yen:Double){
def add(that:Yen):Yen = new Yen(this.yen + that.yen)
def sub(that:Yen):Yen = new Yen(this.yen - that.yen)
}
case class Dollar (dollar:Double){
def add(that:Dollar):Dollar = new Dollar(this.dollar + that.dollar)
def sub(that:Dollar):Dollar = new Dollar(this.dollar - that.dollar)
}
case class Euro (euro:Double){
def add(that:Euro):Euro = new Euro(this.euro + that.euro)
def sub(that:Euro):Euro = new Euro(this.euro - that.euro)
}
object Main extends App {
// 暗黙的な型変換メソッド群をインポートする.
import ImplicitFunctions._
val yen_3 = new Yen(3.0)
val dollar_4 = new Dollar(4.0)
val euro_5 = new Euro(5.0)
// 異なる通貨間で演算可能になる.
print(yen_3.add(dollar_4))
print(dollar_4.add(euro_5))
print(euro_5.add(yen_3))
}