专门研究一种采用类型参数的方法

时间:2012-10-28 10:34:17

标签: scala

我想编写具有类型参数化方法的通用的,可能很慢的实现的代码,该方法适用于实现某个接口的所有类,但仍允许子类根据需要使用更高效的实现来专门化此方法。 / p>

但是,以下代码不能正常工作

class A(val i:Int)

class B {
    def f[T](t:T) = println(t.toString)
}

class C extends B { 
    override def f[A](a:A) = println(a.i * a.i) 
}

因为它将C类中的A视为类型参数,而不是在类型参数仅为A的情况下覆盖函数。

有没有办法编写我想要的代码而不在运行时使用匹配?

1 个答案:

答案 0 :(得分:0)

你想要的是:

scala> class A(val i: Int)
defined class A

scala> class B { 
     |   def f[T](t: T) = println(t.toString)
     | }
defined class B

scala> class C extends B { 
     |   override def f[T <: A](a: T) = println(a.i * a.i) 
     | }
<console>:10: error: overriding method f in class B of type [T](t: T)Unit;
 method f has incompatible type
         override def f[T <: A](a: T) = println(a.i * a.i) 

但正如类型系统告诉你的那样,错误。你违反了Liskov substitution principle

您可以做的是使T成为类级别类型参数或抽象类型成员。然后你可以在子类中约束它,如下所示:

scala> class B {
     |   type T
     |   def f(t: T) = println(t.toString)
     | }
defined class B

scala> class C extends B {
     |   type T = A
     |   override def f(a: T) = println(a.i * a.i)
     | }
defined class C

scala> (new C).f(new A(11))
121

您尚未提供更多信息,因此我不知道这是否适用于您的具体情况。

修改

这是一种特定事物的方法:使用类型类。代码:(结果比预期的更令人费解。)

scala> :paste
// Entering paste mode (ctrl-D to finish)

case class A(i: Int)

case object B

trait F[-A] {
  def f(a: A): Unit
}

trait FLowPriorityImplicits {
  implicit object FAny extends F[Any] {
    def f(a: Any) = println(a.toString)
  }
}

trait FImplicits extends FLowPriorityImplicits {
  implicit object FA extends F[A] {
    def f(a: A) = println(a.i * a.i)
  }
}

object F extends FImplicits

def f[A](x: A)(implicit f: F[A]) = f.f(x)

// Exiting paste mode, now interpreting.

defined class A
defined module B
defined trait F
defined trait FLowPriorityImplicits
defined trait FImplicits
defined module F
f: [A](x: A)(implicit f: F[A])Unit

scala> f(B)
B

scala> f(A(2))
4