1

マニフェストを含めないと、暗黙的な変換でコンパイラ エラーが発生する状況があります。

import scala.language.implicitConversions

abstract class Thing[+A] {
  def get:A
}

case class SubThing[+A](a:A) extends Thing[A] {
  def get = a
}

object Thing {
  implicit def anyToThing[A](a:A):Thing[A] = SubThing(a)
}

object Funcs {
  def f(x:Thing[Int]) = x.get + 1
  def f(x:Thing[Double]) = x.get + 1.0
}

object Main {
  def main(args:Array[String]) = {
    println(Funcs.f(1))
  }
}

あげる

error: ambiguous reference to overloaded definition,
       both method f in object Funcs of type (x: Thing[Double])Double
       and  method f in object Funcs of type (x: Thing[Int])Int
       match argument types (Int) and expected result type Any
println(Funcs.f(1))
              ^

ただし、暗黙的な変換で A の暗黙的なマニフェストを渡すと、次のようになります。

import scala.language.implicitConversions

abstract class Thing[+A] {
  def get:A
}

case class SubThing[+A](a:A) extends Thing[A] {
  def get = a
}

object Thing {
  implicit def anyToThing[A:Manifest](a:A):Thing[A] = SubThing(a)
}

object Funcs {
  def f(x:Thing[Int]) = x.get + 1
  def f(x:Thing[Double]) = x.get + 1.0
}

object Main {
  def main(args:Array[String]) = {
    println(Funcs.f(1))
  }
}

コードを正常にコンパイルします。これはなぜですか?私たちのコードベースにはこの実際の例があり、一般的な状況で暗黙的な変換に依存している場合、多くの 'no Manifest for T' エラーが発生しますが、ラッパー クラスを明示的に作成することによって排除されます。ただし、その暗黙的な変換からマニフェストを取得できれば理想的です。なぜそれが必要なのですか、またはマニフェストを回避しながら同じことを達成する別の方法はありますか?

4

2 に答える 2

0

これは、Thing に変換されると型消去が開始され、Thing[Int] または Thing[Double] ではなく Thing[_] になるため、次のメソッドのオーバーロードが機能しないために発生すると考えられます。

object Funcs {
  def f(x:Thing[Int]) = x.get + 1
  def f(x:Thing[Double]) = x.get + 1.0
}

マニフェストは、あまり扱ったことがないので少し理解が途切れるところですが、メソッドのオーバーロードが機能するように型を保持していると思います。

私が信じているマクロを使用してこれを回避できますが、コンパイラが Int または Double であると確信していなかったものに対して Funcs.f() を呼び出すことはできません。

于 2013-10-10T20:41:27.973 に答える