Как косвенно передать неявный аргумент

Я ожидаю, что приведенный ниже код распечатает 1 и 2. Но я получаю default и default. Когда я явно пересылаю (?) неявное значение, используя закомментированный код, я вижу желаемый результат. Кто-нибудь может объяснить, как это работает? То, что я пытаюсь, невозможно? Я совершенно новичок в Scala. Что я должен прочитать, чтобы понять это глубже?

case class Context(id: Option[String])
object Context {
  implicit val context = Context(Some("default"))
}

class ToolBuilder (id: String) {
  implicit val context = Context(Some(id))
  def extract() = ToolCreatorA.create()
}

case class ToolCreatorA(id: String)
object ToolCreatorA {
  def create() = ToolCreator.create()
  //def create()(implicit context: Context) = ToolCreator.create()
  object ToolCreator {
    def create()(implicit context: Context) = context.id.getOrElse("null")
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    println(new ToolBuilder("1").extract())
    println(new ToolBuilder("2").extract())
  }
}

person perreal    schedule 11.03.2017    source источник


Ответы (1)


Из Scala-документации неявного это два правила: для определения значения неявного параметра.

Во-первых, приемлемыми являются все идентификаторы x, к которым можно получить доступ в момент вызова метода без префикса и которые обозначают неявное определение или неявный параметр.

Во-вторых, подходящими также являются все члены сопутствующих модулей типа неявного параметра, которые помечены как неявные.

Итак, в вашем случае давайте сначала посмотрим, что произойдет, когда мы используем def create() = ToolCreator.create(). Здесь ToolCreator.create() вызовет метод create объекта-компаньона ToolCreator, который ожидает неявный Context def create()(implicit context: Context) = context.id.getOrElse("null")

  1. Теперь наше первое правило гласит, что метод будет искать неявный параметр во всех переменных, к которым у него есть доступ, до того, как вызов метода имел место. Мы видим, что в этот момент нет доступной неявной переменной.
  2. Затем второе правило заключается в том, чтобы искать неявную переменную в сопутствующем объекте неявного типа. В нашем случае неявное значение имеет тип Context, и у нас есть объект-компаньон Context, в котором определена хорошая неявная переменная. Таким образом, это значение будет получено в методе create. object Context { implicit val context = Context(Some("default")) }
  3. Теперь, если мы используем def create()(implicit context: Context) = ToolCreator.create() , этот метод создания вызывается из

    class ToolBuilder (id: String) { implicit val context = Context(Some(id)) def extract() = ToolCreatorA.create() }

  4. Как видите, здесь перед вызовом метода create у него есть переменная контекста, доступная для использования как неявная. Таким образом, это значение будет выбрано.

Полезные ссылки:

  1. Понимание неявного в Scala

  2. http://www.drmaciver.com/2008/03/an-introduction-to-implicit-arguments/

  3. http://www.artima.com/pins1ed/implicit-conversions-and-parameters.html#21.5

person Tawkir    schedule 11.03.2017
comment
так что это означает, что в моем случае использование неявного параметра бессмысленно - person perreal; 11.03.2017
comment
это зависит от того, я не понял вашего намерения использовать имплициты. - person Tawkir; 11.03.2017
comment
я намерен сделать реализацию ToolCreatorA прозрачной для неявного параметра, который я ввожу. Фактический код имеет еще несколько уровней, пока я не достигну ToolCreator. - person perreal; 11.03.2017