This is what you had:
scala> object Foo {
| ???
| val x = 100
| }
defined object Foo
scala> object Bar {
| import Foo._
| def speak = "bar!"
| }
defined object Bar
scala> Bar.speak
res0: String = bar!
scala> Bar.speak
res1: String = bar!
import Foo._ means that for compilation purposes to resolve names members of Foo will be available in the scope.
It does not mean that Foo has to be initialized at this point - Scala is being lazy here.
Now contrast with this example:
scala> object Foo {
| ???
| val x = 100
| }
defined object Foo
scala> object Bar {
| val blowUp = Foo.x
| def speak = "bar!"
| }
defined object Bar
scala> Bar.speak
scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225)
... 37 elided
It forces Foo to get initialized because it uses Foo.x in its own initialization which in turn is triggered by
calling speak. Simplified example:
scala> object Foo {
| ???
| val x = 100
| }
defined object Foo
Didn't blow up yet. Foo is not initialized.
scala> Foo.x
scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225)
... 35 elided
Now we forced Foo to get initialized.
In short there are 2 important things here: 1) lazy initialization upon reference/call and 2) import does not cause initialization.