如何在Scala继承类型T中提取方法

时间:2018-01-22 15:56:58

标签: scala types

让我说我写了一个特质

trait myTrait[T]{
  def plus:(T,T)=>T
  def times:(T,T)=>T
}

如果我的班级想要使用T.type给出的方法,我可以写成:

class myClass[T](val array:Iterable[T]){

  def plus:(T,T) =>T ={
    val typ = ClassTag[T]
    typ match {
      case value if value <:< AnyVal => 
        val numeric = Numeric[T]
        numeric.plus
      case _:customType =>
        CustomType.plus
    }
  }
}

我认为通过反映Class是一种过滤某些类的方法, 但是如何提取那些提供的方法。

1 个答案:

答案 0 :(得分:0)

没有Scala不是这样设计的。一种简单但有限的方法是使用“F-bound”特征来指定这样的操作:

trait Plus[T <: Plus[T]] {
  def plus(other: T): T
}

case class MyInt(value: Int) extends Plus[MyInt] {
  override def plus(other: MyInt): MyInt = MyInt(value + other.value)
}

class Col[T <: Plus[T]](val array: Iterable[T]) {
  def sum(): T = {
    array.reduce((a, b) => a.plus(b))
  }
}

明显的缺点是您无法将特征添加到现有类中。

您在示例中尝试执行的操作看起来有点像type class。在Scala中实现它的方法是这样的:

trait HasPlus[T] {
  def plus(x: T, y: T): T
}

case class MyInt(value: Int) {
  def plus(other: MyInt): MyInt = MyInt(value + other.value)
}

object HasPlus {
  implicit def numeric[T: Numeric] = new HasPlus[T] {
    override def plus(x: T, y: T) = implicitly[Numeric[T]].plus(x, y)
  }

  implicit val myInt = new HasPlus[MyInt] {
    override def plus(x: MyInt, y: MyInt) = x.plus(y)
  }
}

class Col[T: HasPlus](val array: Iterable[T]) {
  def sum(): T = {
    array.reduce((a, b) => implicitly[HasPlus[T]].plus(a, b))
  }
}

请注意,您可以通过定义可以将一个证据转换为另一个证据的Numeric[T]方法,将HasPlus[T]“转换为implicit。对于一个简单的特定课程,您可以implicit val

显示MyInt