使用implicits在特征层次结构的多个级别注入方法

时间:2016-02-10 16:30:18

标签: scala implicits

我正在尝试使用现有的特征层次结构(我无法控制)并在顶层注入一个方法(然后在层次结构中需要自定义处理的每个点覆盖该方法)。隐含地使用这些特征。下面是一个精简的示例,显示了特征层次结构设置和隐式用法;然后我(失败)尝试注入方法。

使用未实现的方法定义父特征,具有指定类型的子特征和方法的实现形式。创建一个隐含的儿童特质。

trait ParentTrait[T] {
  def doSomething1(x: T): T
}

trait ChildTrait extends ParentTrait[Double] {
  override def doSomething1(x: Double): Double = {
    return x + 1.0
  }
}

implicit object ChildTrait extends ChildTrait

定义一个类和函数以隐式使用Parent Trait并调用该方法。

class Utilizer1() {
  def utilize[T](x: T)(implicit trt: ParentTrait[T]): Unit = {
    println(trt.doSomething1(x))
  }
}

调用方法,指定将隐式拾取Child Trait的类型(Double)。 (这很好用。)

new Utilizer1().utilize[Double](1.0)

这里有些东西不起作用:在父Trait上“注入”一个新方法,并在Child Trait中覆盖它。 (显然,这不是正确的方法 - 如何完成这一部分?)

implicit class BetterParentTrait[T](trt: ParentTrait[T]) {
  def doSomething2(x: T): T = ???
}
implicit class BetterChildTrait(trt: ParentTrait[Double]) extends BetterParentTrait[Double](trt) {
  override def doSomething2(x: Double): Double = {
    return x + 2.0
  }
}

定义一个类和函数以隐式使用Parent Trait并调用SECOND方法。

class Utilizer2() {
  def utilize[T](x: T)(implicit trt: ParentTrait[T]): Unit = {
    println(trt.doSomething2(x))
  }
}

调用方法,指定类型(Double)。它不会隐式地拾取Child Trait而是抛出NotImplementedError。所以它确实找到了doSomething2方法(没有编译错误)但它不尊重层次结构并使用顶层的未实现形式。

new Utilizer2().utilize[Double](1.0)

2 个答案:

答案 0 :(得分:0)

您正在执行聚合而不是继承。

BetterParentTrait[T](trt: ParentTrait[T])

这意味着utilize方法不会看到您的隐式类,因为它具有不同的父/接口。 它必须实现ParentTrait类才能隐式传递给上述方法。

implicit class BetterParentTrait[T] extends ParentTrait[T]{
  def doSomething(x: T): T = ???
  def doSomething2(x: T): T = ???
}

答案 1 :(得分:0)

这有帮助吗?

object MainUtilizers {

  trait ParentTrait[T] {
    def doSomething1(x: T): T
  }

  trait ChildTrait extends ParentTrait[Double] {
    override def doSomething1(x: Double): Double = {
      return x + 1.0
    }
  }


  trait BetterParentTrait[T] {
    def doSomething2(x: T): T = ???
  }

  trait  BetterChildTrait extends BetterParentTrait[Double] {
    override def doSomething2(x: Double): Double = {
      return x + 2.0
    }
  }

  //implicit object ChildTrait extends ChildTrait // Commented to avoid 2 implicits for ParentTrait[Double]

  implicit object BetterChildTrait extends BetterChildTrait with ChildTrait

  class Utilizer1() {
    def utilize[T](x: T)(implicit trt: ParentTrait[T]): Unit = {
      println(trt.doSomething1(x))
    }
  }
  class Utilizer2() {
    def utilize[T](x: T)(implicit trt: BetterParentTrait[T]): Unit = {
      println(trt.doSomething2(x))
    }
  }

  def main(args: Array[String]) {
    new Utilizer1().utilize[Double](1.0)

    new Utilizer2().utilize[Double](1.0)
  }
}