Lazy vals и неявные параметры в Scala

Я пытался понять, как работают неявные параметры в Scala. Насколько я могу судить, неявное разрешение параметров выглядит примерно так:

  1. Явная передача объекта методу.
  2. неявные определения, определенные в области видимости.
  3. Сопутствующий объект класса, используемый в качестве неявного параметра.

Однако, когда я начал экспериментировать с этим в сочетании с lazy vals, я немного удивился. Кажется, что ленивые валы используют только последние правила разрешения. Вот пример кода для иллюстрации:

class Bar(val name:String)
object Bar { implicit def bar = new Bar("some default bar") }

class Foo {
  lazy val list = initialize
  def initialize(implicit f:Bar) = {
    println("initialize called with Bar: '" + f.name + "'...")
    List[Int]()
  }
}

trait NonDefaultBar extends Foo {
  implicit def f = new Bar("mixed in implicit bar")
  def mixedInInit = initialize
  lazy val mixedInList = list
}

object Test {
    def test = {
      println("Case 1: with implicitp parameter from companion object")
      val foo1 = new Foo
      foo1.list
      foo1.initialize

      println("Case 2: with mixedin implicit parameter overriding the default one...")
      val foo2 = new Foo with NonDefaultBar 
      foo2.mixedInList

      val foo3 = new Foo with NonDefaultBar 
      foo3.mixedInInit

      println("Case 3: with local implicit parameter overriding the default one...")
      implicit def nonDefaultBar = new Bar("locally scoped implicit bar")
      val foo4 = new Foo 
      foo4.list
      foo4.initialize
    }
}

Вызов Test.testдает следующий результат:

Case 1: with implicitp parameter from companion object 
initialize called with Bar: 'some default bar'... 
initialize called with Bar: 'some default bar'... 
Case 2: with mixedin implicit parameter overriding the default one... 
initialize called with Bar: 'some default bar'... 
initialize called with Bar: 'mixed in implicit bar'... 
Case 3: with local implicit parameter overriding the default one... 
initialize called with Bar: 'some default bar'... 
initialize called with Bar: 'locally scoped implicit bar'...

Почему компилятор не улавливает наличие неявного Bar при вызове mixInList в Случае 2. В Случае 3 он также пропускает локально определенный неявный Bar при доступе к списку.

Существуют ли какие-либо способы использования неявных параметров с ленивыми значениями, которые не используют неявные параметры, определенные в сопутствующем объекте?

8
задан Emil H 15 April 2012 в 13:40
поделиться