2011-10-15 27 views
5

Cố gắng phân biệt phương thức nào được gọi dựa trên loại tham số thứ hai, Bất kỳ so với Throwable, nhưng không thành công. Biên dịch mã dưới đây tạo ra các thông báo lỗi sau:Các loại, Tuples, Ưu tiên tiềm ẩn và Phương pháp quá tải

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 

Dưới đây là các mã:

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

tôi đã cố gắng làm cho "t2" ưu tiên thấp hơn như sau:

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

và loại bỏ " t2 "từ đối tượng" Gọi "nhưng có cùng thông báo lỗi.

Tôi muốn định hướng diễn ra vào thời gian biên dịch chứ không phải lúc chạy. Cảm ơn.

Trả lời

2

Miles Sabin cung cấp cho tôi với các giải pháp sau đây:

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") 
     } 
     } 
    } 
Các vấn đề liên quan