Reputation: 228
Let's say I'm trying to write a simple Tic-Tac-Toe game. It has an M x N field. The game has only one field, so it probably should be represented with a singleton object
. Like this:
object Field {
val height : Int = 20
val width : Int = 15
...
}
But I don't want to hardcode the height and width, so it would be nice if those could be passed to the object at runtime, via a constructor or something. But object
s cannot have constructors.
Well, I could change height
and width
to be var
s, and not val
s and introduce a new method
def reconfigure (h:Int, w:Int) = {
height = h
width = w
}
and call it at the begining of the game. But it's not elegant as well.
So, is there a neat way of doing this - i.e. having object val
s initialized with values not known before runtime?
Upvotes: 15
Views: 19459
Reputation: 92046
Why not use a class
and initialize one instance in main
?
case class Field(width: Int, height: Int) {
//...
}
object Main {
def main(args: Array[String]): Unit = {
val field = Field(30, 25)
}
}
Upvotes: 14
Reputation: 3607
You could employ the use of lazy vals. This may make things more complex any you still need to use a var.
case class Config( height: Int, width: Int )
object Field {
val defaultConfig = Config( 20, 15 )
var config: Option[Config] = None
def getConfig = config.getOrElse( defaultConfig )
lazy val height = getConfig.height
lazy val width = getConfig.width
}
object Main extends App {
Field.config = Some( Config( 30, 25 ) )
}
Upvotes: 15
Reputation: 10852
One option is lazy vals:
object Field {
lazy val height = // code to find height
lazy val width = // code to find width
}
The val will be initialised the first time it's used, so as long as you don't use them until you have all the information you need to initialise them, you should be good.
Upvotes: 3