1

我有以下抽象类:

abstract class FieldProvider[+T: Writes](db: DB)(implicit i: RequestAction, j: ExecutionContext) {}

和以下实现:

class LengthProvider extends FieldProvider ...

object LengthProvider extends ((DB) => LengthProvider) {
  def apply(v1: DB): LengthProvider = new LengthProvider(v1)
}

class WidthProvider extends FieldProvider ...

object WidthProvider extends ((DB) => WidthProvider) {
  def apply(v1: DB): WidthProvider = new WidthProvider(v1)
}

我之所以有这些apply方法是因为我需要以下配置图:

val providers: Map[String, ((DB) => FieldProvider)] = Map(
 "length" -> LengthProvider,
 "width"  -> WidthProvider
)

这样我就可以通过包含其名称的字符串来初始化提供者:

providers("length")(db) // returns a new instance of LengthProvider

现在,我的问题是所有这些提供者构造函数都需要两个隐式变量。但我不知道如何将它包含在函数定义(DB) => FieldProvider中。因此,本质上,apply方法签名应该类似于(DB)(implicit RequestAction, ExecutionContext) => FieldProvider,但我不知道我正在尝试做的事情是否有正确的语法。

我也可以放弃并明确传递它们:

object WidthProvider extends ((DB, RequestAction, ExecutionContext) => WidthProvider) {
   def apply(v1: DB, v2: RequestAction, v3: ExecutionContext): WidthProvider = new WidthProvider(v1)(v2,v3)
}

但是我必须在其他地方明确地传递它们,而不是providers("length")(db),我必须写providers("length")(db, implicitly[RequestAction], implicitly[ExecutionContext]),这感觉不对。

4

2 回答 2

2

让我们假设FieldProvider有 2 个需要隐式的方法。避免重复的更方便的方法是将它们作为构造函数级别的隐式参数传递,然后所有内部方法都FieldProvider可以“共享”它们。

但是,这对您当前的类树没有帮助,所以要解决这个问题,而不是这样做:

abstract class FieldProvider()(implicit param1: X1..) {
  def test: T = param1.doSomething
}

只需将隐式移动到方法级别,以便您可以在与扩展构造函数不同的时间提供它。

abstract class FieldProvider() {
  def test()(implicit param1: X1): T = param1.doSomething
}
于 2016-04-13T08:45:19.813 回答
0

因此,本质上,apply方法签名应该类似于(DB)(implicit RequestAction, ExecutionContext) => FieldProvider,但我不知道我正在尝试做的事情是否有正确的语法。

请注意,您可能会直接获得(在未来的 Scala 2017 版本中)隐式函数类型

请参阅Odersky本人的pull request 1775 。

让我们f1通过将最后一个参数部分移动到等号右侧来稍微定义一下:

def f1(x: Int) = { implicit thisTransaction: Transaction =>
  thisTransaction.println(s"first step: $x")
  f2(x + 1)
}

这个新版本的 f1 的右侧现在是一个隐式函数值。
这个值的类型是什么?
以前是Transaction => Int,即函数具有隐式参数的知识在类型中丢失了。

拉取请求实现的主要扩展是引入隐式函数类型,这些类型反映了我们已经拥有的隐式函数值。
具体来说,新的f1类型是:

implicit Transaction => Int

就像正常的函数类型语法一样A => B,desugars to scala.Function1[A, B],隐式函数类型语法implicit A => Bdeugars to scala.ImplicitFunction1[A, B]
这同样适用于其他函数。合并dotty的 pull request #1758后,此类功能不再有 22 的上限。

于 2016-12-10T21:15:51.623 回答