Scala泛型隐式值在重载时是不明确的?

时间:2013-05-15 12:52:10

标签: scala implicit

以下输出0而不是我想要的结果,即2。 这看起来类似于this question,但在这里我到处使用括号。

object Test {
  implicit def x = List(1, 2)

  trait A[T] {
    def res(): Int = 0
    def makeResPlusOne(): Int = res() + 1    // All right
  }
  trait B[T] extends A[T] {
    def res()(implicit y: List[T]) = y.size
  }
  class AA extends A[Int]
  class BB extends B[Int]
}
val x: Test.A[Int] = new Test.BB
x.res() // Outputs 0 instead of 2.

我希望最后的结果显然是2,y的大小,但输出0。 如果我将关键字override添加到B[T]中的方法,则表示它会覆盖任何内容。 如果我将隐式参数添加到A[T]中的方法res,就像那样......

object Test {
  implicit def x = List(1, 2)

  trait A[T] {
    def res()(implicit y: List[T]): Int = 0  // Added the implicit keyword.
    def makeResPlusOne(): Int = res() + 1    // Fails to compile.
  }
  trait B[T] extends A[T] {
    override def res()(implicit y: List[T]) = y.size
  }
  class AA extends A[Int]
  class BB extends B[Int]
}
val x: Test.A[Int] = new Test.BB
x.res() // Error

...它引发了以下错误:

error: could not find implicit value for parameter y: List[Int]

我做错了什么?如何在子类中获得隐式值的好处,并且仍能够重载超级方法?

修改

如果我导入隐式,它可以工作。但是,我有方法makeResPlusOne(),它在第二种情况下触发错误,但在第一种情况下不触发。请告诉我如何正确定义此方法,通常在编译时不需要隐式。 _

 error: could not find implicit value for parameter y: List[T]
    def makeResPlusOne(): Int = res() + 1
                                ^

2 个答案:

答案 0 :(得分:4)

你很亲密:

object Test {
  implicit def list = List(1, 2)

  trait A[T] {
    def res()(implicit y: List[T]): Int = 0  // Added the implicit keyword.
  }
  trait B[T] extends A[T] {
    override def res()(implicit y: List[T]) = y.size
  }
  class AA extends A[Int]
  class BB extends B[Int]
}
import Test.list
val x: Test.A[Int] = new Test.BB
x.res() // Works!

您忘记导入隐式列表。请注意,在使用变量x导入时,我已重命名隐式以避免冲突。

编辑:

如果您需要def makeResPlusOne()(implicit y: List[T]): Int = res() + 1,则需要在范围内包含隐式List[T],因此您还必须添加(implicit y: List[T])

object Test {
  implicit def xx = List(1, 2)

  trait A[T] {
    def res()(implicit y: List[T]): Int = 0
    def makeResPlusOne()(implicit y: List[T]): Int = res() + 1 // Works now.
  }
  trait B[T] extends A[T] {
    override def res()(implicit y: List[T]) = y.size
  }
  class AA extends A[Int]
  class BB extends B[Int]
}
import Test.xx // import the implicit list
val x: Test.A[Int] = new Test.BB
x.res() // Works

答案 1 :(得分:2)

此代码适用于我(请注意,我将隐式内容从def更改为val):

object Test {
  implicit val xx = List(1, 2)

  trait A[T] {
    def res()(implicit y: List[T]): Int = 0  // Added the implicit keyword.
  }
  trait B[T] extends A[T] {
    override def res()(implicit y: List[T]) = y.size
  }
  class AA extends A[Int]
  class BB extends B[Int]

  val x: Test.A[Int] = new Test.BB
  x.res()  
}

不确定这是否仍然符合您的需求。根本问题确实是,正如编译器告诉你的那样,你在范围内没有隐式List[Int]。我的示例将x.res()调用移动到Test对象中,因此将其置于范围内,但您也可以将现有的隐式导入到@Stephane Godbillon所提及的范围内。