LoginSignup
6
2

More than 5 years have passed since last update.

結果型を省略したimplicit定義は実際に使用される箇所の"後ろ"に書いてはいけない

Posted at

TL;TR

暗黙の型変換/暗黙のパラメーターで結果型/型注釈を明示しない場合に、実際に使われる箇所と同一ソース上で後ろに定義するとコンパイルエラーになる

環境

Scala 2.11.7

解説

自分で書いててよく分からなかったのでコードで見てみる。

class Foo(str: String) {
  def bar() = println("bar")
}

object Main extends App {
  "hoge".bar()
  implicit def stringToFoo(str: String) = new Foo(str)
}

以上のコードは暗黙の型変換が上手くいかずにコンパイルエラーとなる。

Error:(8, 10) value bar is not a member of String
Note: implicit method stringToFoo is not applicable here because it comes after the application point and it lacks an explicit result type
"hoge".bar()

これはOdersky先生曰く

An implicit conversion without explicit result type is visible only in the text following its own definition. That way, we avoid the cyclic reference errors.

暗黙の型変換の定義の結果型を省略した場合、定義より前で型変換を行うことはできないようだ。

コンパイルエラーを避けるには、

  • 結果型を明示する
object Main extends App {
  "hoge".bar()
  implicit def stringToFoo(str: String): Foo = new Foo(str)
}
  • 型変換が行われる箇所よりも前で定義する
object Main extends App {
  implicit def stringToFoo(str: String) = new Foo(str)
  "hoge".bar()
}

これで無事コンパイルが通るようになる。


このエラーは次のようなコードでも発生する。

object Main {
  import Sub._
  "hoge".bar()
}
object Sub {
  implicit def stringToFoo(str: String) = new Foo(str)
}

MainオブジェクトはSubオブジェクトから暗黙の型変換の定義をimportしている。実は、このエラーは 同一ソースファイル内ならスコープ関係なく発生する。
なのでエラーを消すには上述した通り、結果型を明示するか、SubオブジェクトをMainオブジェクトの上に書くか、あるいはMainとSubを別々のソースファイルに書けばよい。


さらに、暗黙のパラメーターでも同じようなエラーが発生する。

object Fuga {
  def doSomething(str: String)(implicit num: Int) = println(str + num)
}
object Hoge {
  import Piyo._
  Fuga.doSomething("a") //コンパイルエラー!
}
object Piyo {
  implicit val num = 1
}

implicit valの型注釈が省略されていることに注意してほしい。この場合も暗黙の型変換の場合と同じように、暗黙のパラメーターが使用される箇所より後ろに定義することができない。

コンパイルエラーを解消するにはやはり、型注釈を明示するか、PiyoをHogeの上に書くか、ソースファイルを分けることが必要になる。

結論

implicit使うときは結果型/型注釈を書こう。

参考

6
2
0

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
6
2