I'm running into a standard problem as a newbie to Scala: How do I define two classes in such a way that I can make an instance of one that the other as member variable, which in turn points back to the first instance?
I would like to end up with an instance of Game which has a member of type Dealer which has a member of type Game, which is in fact the original Game instance
So in this case each instance (Game, Dealer) has a member which is the other instance. Can anyone guide me to the right way to to this?
Forward reference is when you declare a type but do not define it. It allows you to use the type by pointer (or reference for C++) but you cannot declare a variable. This is a way to say to the compiler that something exists. Say that you have a Plop structure defined in Plop.
A forward reference occurs when a label is used as an operand, for example as a branch target, earlier in the code than the definition of the label. The assembler cannot know the address of the forward reference label until it reads the definition of the label.
0. forward reference extends over definition of variable.
Java allows very flexible forward references. A method may refer to a variable or another method of its class, regardless of where in the current class the variable or method is defined.
If you really need to make the classes immutable your only option is to use by name parameters in the constructor and always create instances as lazy val
s:
class Dealer(val name: String, g: => Game) {
lazy val game = g
override def toString = "Dealer(name=%s, game=%s)".format(name, game.name)
}
class Game(val name: String, d: => Dealer) {
lazy val dealer = d
override def toString = "Game(name=%s, dealer=%s)".format(name, dealer.name)
}
lazy val game: Game = new Game("Doppelkopf", new Dealer("Peter", game))
lazy val dealer: Dealer = new Dealer("Tina", new Game("Poker", dealer))
Note that you need the type ascription on the lazy vals or it will not compile.
You have two choices here:
To see why, consider the following transformation between (immutable) trees. These are both defined with each parent node holding a list of child nodes, but children don't know their parent:
a (a)
b (b)
c c
d --> (d)
e e
f f
g g
Specifically, the node d
was cloned with the new value. To do this, we also had to clone all the parent nodes (shown in brackets).
If nodes held their parent, then c
would have to be "updated" to reflect the new b
node, and e, f, g
would have to be updated to reflect the new a
node. i.e. the entire tree would have to be copied!
By only holding relationships in one direction, from parent to child, it becomes possible to reuse c, e, f, g
across successive versions of the structure. This is a powerful optimisation, and is key to writing efficient functional algorithms.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With