【问题标题】:method overloading with a parameterized type具有参数化类型的方法重载
【发布时间】:2014-04-02 16:15:23
【问题描述】:

只是想知道是否有一种方法可以使用参数化类型调用重载方法。例如定义如下对象:

object Wrap {

        def f(x: X) = println("x called")
        def f(y: Y) = println("y called")
        def f(a: Any) = println("Any")

        def fp[T](t: T) = f(t)
}

当我进行以下调用测试时

Wrap.fp(new X())

它去调用Any。有没有办法让我从 fp() 调用适当的 f?

【问题讨论】:

    标签: scala


    【解决方案1】:

    两种方法:

    第一种方式假设XY 是已知类型而不是泛型类型。然后您可以执行以下操作:

     def fp: PartialFunction[Any,Unit] ={
       case x: X => println("got x")
       case y: Y => println("got y")
       case _ => println("Any")
     }
    

    而且不用做太多体操也能很好地工作。

    第二种方式,使用类型类:

     def fp[T](t: T)(implicit f: Caller[T]) = f(t)
    

    也就是说,您的类型类可能希望如下所示:

     trait Caller[T]{
       def apply(t: T)
     }
    

    您将实际事物放在范围内并使用解析顺序找到最终的Caller[Any],以便其他所有内容优先。所以我会这样做:

     object Wrap{
       implicit val xCal = new Caller[X]{
         def apply(x: X){ println("x called") }
       }
       implicit val yCal = new Caller[Y]{
         def apply(x: Y){ println("y called") }
       }
     }
    
     object `package`{
       implicit val anyCal = new Caller[Any]{
         def apply(t: Any){ println("any") }
       }
     }
    

    【讨论】:

    • 我想知道IDE是否有第二种方式作为快速修复重构。
    【解决方案2】:

    使用类标签进行辅助匹配:

    scala> class W[A: ClassTag] { def f(x: X) = 1; def f(y: Y) = 2; def f(a: A) = 3; 
         | def g(x: Any) = x match {
         | case v: X => f(v); case v: Y => f(v); case v: A => f(v); case _ => -1 } }
    defined class W
    
    scala> trait Z
    defined trait Z
    
    scala> val w = new W[Z]
    w: W[Z] = W@1685b453
    
    scala> w g new X {}
    res6: Int = 1
    
    scala> w g new Y {}
    res7: Int = 2
    
    scala> w g new Z {}
    res8: Int = 3
    
    scala> w g "hi"
    res9: Int = -1
    

    在真正的 API 中,g 会采用一个类型参数,它是各种参数的某个超类型,因为没有人编写采用 Any 的 API。 OP 中的T 参数基本上是Any,因为它是不受约束的。

    在我编辑的时候,我们忘了说重载是邪恶的。

    【讨论】:

    • @som-snytt 为什么需要在A 上绑定上下文?即使没有A: TypeTag,它仍然可以工作。你能解释一下吗
    • @Jatin 我没注意。谢谢,我更正了用例。我想我会转到另一个答案,问他们为什么需要一个类型参数。
    【解决方案3】:
    def process[A](a: A) = a match {
      case c: X => Wrap f c
      case d: Y => Wrap f d
      case _ => Wrap f a 
    }
    

    【讨论】:

    • 是的,它不能真正按照我想要的方式完成,但匹配表达式对我来说是最好的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-27
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多