My understanding is that everything in the object block is evaluated when you reference the object. And
object Hello {
def square(x: Int) = x * x
println("Hello, World!")
}
behaves like
object Hello {
def square(x: Int) = x * x
val _ = println("Hello, World!")
}
because println() produces a side effect and returns Unit/(), which in this case is discarded right away. So the printing is just a side effect that is produced when evaluating the object. Also take note of the following example:
object Hello {
def square(x: Int) = x * x
println("Hello, World!")
}
object main extends App {
println("first")
Hello
println("second")
println(Hello.square(2))
println("third")
}
this prints
first
Hello, World!
second
4
third
so the printing of hello world happens only once and it happens when Hello is referenced, not when square() is called.
Normally, you would not want to have code that produces side effects within an object. This is more a place for functions and values/variables. E.g.:
object Hello {
val w = "World"
def greet(what: String): Unit = println(s"Hello, $what!")
}
object main extends App {
Hello.greet(Hello.w)
Hello.greet("Scala")
}
Or if you want the value to be dynamic, you can use a class instead:
class Hello(val w: String) {
def greet(what: String): Unit = println(s"Hello, $what!")
}
object main extends App {
val h = Hello("World")
h.greet(h.w)
h.greet("Scala")
}
Edit: Changed some incorrect details of the initial answer.