LoginSignup
1

More than 5 years have passed since last update.

レシーバの暗黙の型変換についてのメモ

Posted at

Scala 2.11.7

Example code

class A {
  def meth() = println("A.meth()")
}
object A {
  implicit def bool2A(b: Boolean): A = new A()
}

コンパニオンオブジェクト

レシーバの場合、変換先のコンパニオンオブジェクトで定義したimplicitはタダでは使えないので、importか型注釈を追加する必要がある。(変換元なら問題なし)

object Main extends {
  import A._
  def main(args: Array[String]) = {
    true meth // import無しではエラー
    (true: A) meth
  }
}

おそらくメソッドから変換先の型を推論するので、importしたコンパニオンオブジェクトだけを対象とすることで探索が複雑にならないようにしているのだと思う。

implicitの候補が複数ある場合

親子

object Main extends {
  import A._
  import B._
  def main(args: Array[String]) = {
    true meth
  }
}

class B extends A {
  override def meth() = println("B.meth()")
}

object B {
  implicit def bool2B(b: Boolean): B = new B()
}

importの順序を変えてもB.meth()が呼ばれるので、サブクラスを優先するものと思われる。(ちなみに引数の変換の場合は、引数の型に依存)

兄弟

object Main extends {
  import B._
  import C._
  def main(args: Array[String]) = {
    true meth
  }
}

class B extends A {
  override def meth() = println("B.meth()")
}

object B {
  implicit def bool2B(b: Boolean): B = new B()
}

class C extends A {
  override def meth() = println("C.meth()")
}

object C {
  implicit def bool2C(b: Boolean): C = new C()
}

曖昧なのでコンパイルエラー。

ImplicitConversion.scala:5: error: type mismatch;
 found   : Boolean(true)
 required: ?{def meth: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method bool2B in object B of type (b: Boolean)B
 and method bool2C in object C of type (b: Boolean)C
 are possible conversion functions from Boolean(true) to ?{def meth: ?}
    true meth
    ^

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1