Я ожидаю, что приведенный ниже код распечатает 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())
}
}
Ответ 1 · рейтинг 3 · Tawkir
Из Scala-документации неявного это два правила: для определения значения неявного параметра.
Во-первых, приемлемыми являются все идентификаторы x, к которым можно получить доступ в момент вызова метода без префикса и которые обозначают неявное определение или неявный параметр.
Во-вторых, подходящими также являются все члены сопутствующих модулей типа неявного параметра, которые помечены как неявные.
Итак, в вашем случае давайте сначала посмотрим, что произойдет, когда мы используем def create() = ToolCreator.create(). Здесь ToolCreator.create() вызовет метод create объекта-компаньона ToolCreator, который ожидает неявный Context def create()(implicit context: Context) = context.id.getOrElse("null")
- Теперь наше первое правило гласит, что метод будет искать неявный параметр во всех переменных, к которым у него есть доступ, до того, как вызов метода имел место. Мы видим, что в этот момент нет доступной неявной переменной.
- Затем второе правило заключается в том, чтобы искать неявную переменную в сопутствующем объекте неявного типа. В нашем случае неявное значение имеет тип
Context, и у нас есть объект-компаньон Context, в котором определена хорошая неявная переменная. Таким образом, это значение будет получено в методе create.
object Context {
implicit val context = Context(Some("default"))
}
Теперь, если мы используем def create()(implicit context: Context) = ToolCreator.create() , этот метод создания вызывается из
class ToolBuilder (id: String) {
implicit val context = Context(Some(id))
def extract() = ToolCreatorA.create()
}
Как видите, здесь перед вызовом метода create у него есть переменная контекста, доступная для использования как неявная. Таким образом, это значение будет выбрано.
Полезные ссылки:
Понимание неявного в Scala
http://www.drmaciver.com/2008/03/an-introduction-to-implicit-arguments/
http://www.artima.com/pins1ed/implicit-conversions-and-parameters.html#21.5