类型、元组、隐式优先级和重载方法

发布于 2024-12-09 18:57:06 字数 2648 浏览 0 评论 0原文

尝试根据第二个参数的类型 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”,但得到了相同的错误消息。

我希望消歧发生在编译时而不是运行时。 谢谢。

Trying to disambiguate which method is called based upon the type of the second parameter, Any vs. Throwable, but without success. Compiling the code below generates the following error message:

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

Here's the code:

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")
    }
  }
}

I tried making the "t2" lower priority as follows:

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 {
    ....
 }

and removing "t2" from the "Call" object, but got the same error message.

I would like the disambiguation to take place at compile-time and not at run-time.
Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

与他有关 2024-12-16 18:57:06

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")
        }
      }
    }

Miles Sabin provided me with the following solution:

    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")
        }
      }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文