尝试根据第二个参数Any对Throwable的类型消除歧义,但没有成功。编译下面的代码会生成以下错误消息:
Main.scala:85: error: ambiguous reference to overloaded definition,
both method apply in class Call of type (body: =>(String, Throwable, Array[Any]))(implicit m: Main.Call.Dummy3)Unit
and method apply in class Call of type (body: => (String, Array[Any]))(implicit m: Main.Call.Dummy1)Unit
match argument types ((String, Throwable, String))
agent.call {
^
one error found
以下是代码:
object Main {
object Call {
implicit def t1(t: Tuple2[String, Any]): Tuple2[String, Array[Any]] = {
(t._1, Array(t._2))
}
implicit def t1t(t: Tuple2[String, Throwable]): Tuple2[String, Throwable] = {
(t._1, t._2)
}
implicit def t2(t: Tuple3[String, Any, Any]): Tuple2[String, Array[Any]] = {
(t._1, Array(t._2, t._3))
}
implicit def t2t(t: Tuple3[String, Throwable, Any]): Tuple3[String, Throwable, Array[Any]] = {
(t._1, t._2, Array(t._3))
}
class Dummy1
object Dummy1 {
implicit def dummyImplicit: Dummy1 = {
println("Dummy1.dummyImplicit")
new Dummy1
}
}
class Dummy2
object Dummy2 {
implicit def dummyImplicit: Dummy2 = {
println("Dummy2.dummyImplicit")
new Dummy2
}
}
class Dummy3
object Dummy3 {
implicit def dummyImplicit: Dummy3 = {
println("Dummy3.dummyImplicit")
new Dummy3
}
}
}
import Call._
class Call {
def apply(body: => Tuple2[String, Array[Any]])
(implicit m: Dummy1): Unit = {
println("message and array of parameters")
}
def apply(body: => Tuple2[String, Throwable])
(implicit m: Dummy2): Unit = {
println("message and throwable")
}
def apply(body: => Tuple3[String, Throwable, Array[Any]])
(implicit m: Dummy3): Unit = {
println("message, throwable and array of parameters")
}
}
class Agent {
val _call = new Call
def call: Call = _call
}
def main(args: Array[String]): Unit = {
val msg = "XXX"
val agent = new Agent
agent.call {
(msg, "one")
}
agent.call {
(msg, new Exception)
}
agent.call {
(msg, "one", "two")
}
agent.call {
(msg, new Exception, "one")
}
}
}
我尝试将“t2”置于较低优先级,如下所示:
trait LowPriority {
implicit def t2(t: Tuple3[String, Any, Any]): Tuple2[String, Array[Any]] = {
(t._1, Array(t._2, t._3))
}
}
object Call extends LowPriority {
....
}
并从“Call”对象中删除“t2”,但收到相同的错误消息。
我希望消除歧义在编译时而不是在运行时进行。 感谢。
答案 0 :(得分:2)
Miles Sabin为我提供了以下解决方案:
object Main {
object Call {
trait LowPriorityDistinguishThrowable {
trait Wrap1[A, B] {
val body : (A, B)
def apply(call: Call) : Unit
}
trait Wrap2[A, B, Any] {
val body : (A, B, Any)
def apply(call: Call) : Unit
}
implicit def wrap11[T](body0 : => (String, T)) =
new Wrap1[String, T] {
lazy val body = body0
def apply(call: Call) {
println("(message and not throwable): " +body)
}
}
implicit def wrap21[T](body0 : => (String, T, Any)) =
new Wrap2[String, T, Any] {
lazy val body = body0
def apply(call: Call) {
println("(message and not throwable): " +body)
}
}
}
object DistinguishThrowable extends LowPriorityDistinguishThrowable {
implicit def wrap12(body0 : => (String, Throwable)) =
new Wrap1[String, Throwable] {
lazy val body = body0
def apply(call: Call) {
println("(message and throwable): " +body)
}
}
implicit def wrap22(body0 : => (String, Throwable, Any)) =
new Wrap2[String, Throwable, Any] {
lazy val body = body0
def apply(call: Call) {
println("(message and throwable): " +body)
}
}
}
}
class Call(val enabled: Boolean) {
import Call._
import DistinguishThrowable._
def apply[T](body: Wrap1[String, T]): Unit = {
if (enabled) body(this)
}
def apply[T](body: Wrap2[String, T, Any]): Unit = {
if (enabled) body(this)
}
}
def main(args : Array[String]): Unit = {
val call = new Call(true)
call {
("foo", new Exception)
}
call {
("foo", "bar")
}
call {
("foo", new Exception, "one")
}
call {
("foo", "bar", "one")
}
}
}