如何使用“implicit”作为apply()参数?

时间:2011-06-19 09:32:05

标签: scala implicit apply

我想这样做:

abstract class Context {
    def getInt(id: Int): Int
}

abstract class Dependency[+T]
(val name: String, val id: Int)
extends Function1[Context,T]

class IntDependency(name: String, id: Int)
extends Dependency[Int](name, id) {
    def apply(implicit context: Context): Int =
        context.getInt(id)
}

但后来我收到如下错误信息:

class IntDependency needs to be abstract, since method apply in trait
Function1 of type (v1: Context)Long is not defined (Note that T1 does
not match Context)

我知道implicits通常应该是 second 参数列表的一部分,但是我无法弄清楚如何编码它以便编译,并提供我想要的结果。

说明:我正在尝试创建一个框架,其中可以定义“Function”对象,该对象可以依赖于其他函数来计算它们的值。所有函数应该只接受一个Context参数。上下文知道其他函数的“结果”。函数实例应该是不可变的,状态驻留在上下文中。我希望函数在创建时创建“依赖”字段,它隐式地接受上下文,并在该上下文中返回依赖项的值,以便访问apply方法内部的依赖项“感觉比如“访问参数或字段,没有明确地将上下文作为参数提供给依赖项。

4 个答案:

答案 0 :(得分:5)

您确定需要Dependency延长Function吗?因为如果不这样做,只需将extends Function1[Context,T]部分保留下来,您的代码即可运行。

如果您确实需要延长Function,而不是我所知道的解决方案。但有些情况下您可能会尝试重载apply方法。像这里:

scala> val sum = new Function1[Int, Function1[Int, Int]] {
         |      def apply(a: Int) = (b: Int) => a + b
         |      def apply(a: Int)(implicit b: Int) = a + b
         |}
sum: java.lang.Object with (Int) => (Int) => Int{def apply(a:Int)(implicit b: Int): Int} = <function1>

scala> sum(2)(3)
res0: Int = 5

scala> implicit val b = 10
b: Int = 10

scala> sum(2)
res1: Int = 12

答案 1 :(得分:4)

方法的最终参数部分可以隐含标记;它不一定是第二部分,尽管最常见。

但似乎当子类标记隐式的参数部分时,不再考虑覆盖超类中的方法。

scala> new (Int => Int) { def apply(implicit i: Int) = i }
<console>:8: error: object creation impossible, since method apply in trait Function1 of type (v1: Int)Int is not defined
(Note that T1 does not match Int)
       new (Int => Int) { def apply(implicit i: Int) = i }
           ^

scala> trait F1 { def f(a: Any) }; new F1 { def f(implicit a: Any) = () }
<console>:8: error: object creation impossible, since method f in trait F1 of type (a: Any)Unit is not defined
       trait F1 { def f(a: Any) }; new F1 { def f(implicit a: Any) = () }

                                       ^

规范没有具体提到这个(§5.1.4覆盖),因此它可能是实现限制或错误。

答案 2 :(得分:2)

确定,apply方法签名与implicit不符合Function1.apply的签名。 希望我能正确解决你的问题,那么(假设你的context是可变的,也许是单身的)在创建时注入隐式上下文呢?你的情况可以吗?

class IntDependency(id: Int)(implicit context: Context) extends Dependency[Int](id)

但后来我想知道(之前仍然在想)如何使用context方法处理apply参数。

答案 3 :(得分:2)

以下是工作解决方案:

abstract class Context {
    def getInt(id: Int): Int
}

abstract class Dependency[+T]
(val name: String, val id: Int) {
    def get(context: Context): T
}

class IntDependency(name: String, id: Int)
extends Dependency[Int](name, id) {
    def get(context: Context): Int =
        context.getInt(id)
}

implicit def intDep2Int(dep: IntDependency)
(implicit context: Context): Int =
dep.get(context)