Как использовать «неявный» в качестве параметра apply ()? - PullRequest
5 голосов
/ 19 июня 2011

Я хочу сделать это:

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)

Я понимаю, что имплициты обычно должны быть частью списка параметров second , но я не могу понять, как его кодировать, чтобы он компилировался и давал желаемый результат.

Объяснение: Я пытаюсь создать каркас, в котором можно определить объект "Функция", который может зависеть от других функций для вычисления их значения. Все функции должны принимать только один параметр Context. Контекст знает «результат» других функций. Экземпляры функции должны быть неизменными, а состояние должно находиться в контексте. Я хочу, чтобы функции создавали поля "зависимости" во время создания, которые неявно принимают контекст и возвращают значение зависимости в этом контексте, так что доступ к зависимости внутри метода apply "ощущается как "доступ к параметру или полю, то есть без явного указания контекста как параметра для зависимости.

Ответы [ 4 ]

5 голосов
/ 19 июня 2011

Вы уверены, что вам нужен 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
4 голосов
/ 19 июня 2011

Метод может иметь конечный раздел параметров, помеченный как неявный;это не обязательно должен быть второй раздел, хотя это наиболее часто встречается.

Но кажется, что когда подкласс помечает раздел параметров неявно, он больше не считается переопределением метода в суперклассе.

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 голосов
/ 19 июня 2011

Вот рабочее решение:

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)
2 голосов
/ 19 июня 2011

Он уверен, что ваша подпись метода apply с implicit не соответствует подписи Function1.apply. Надеюсь, я правильно понял вашу проблему, так как насчет (если предположить, что ваш context изменчивый и, возможно, одноэлементный) неявный контекст, внедренный во время создания? Возможно ли это в вашем случае?

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

Но потом я задаюсь вопросом (и до сих пор интересовался), что делать с аргументом context в методе apply.

...