Playing about with a DSL in Scala, so lets say I have something like this:
house {
floor {
bedroom(\"kids)
bedroom(\"master\")
}
floor {
ki
This approach uses mutable fields to set the child-to-parent relation after the involved objects have been created:
/* Data classes */
class House(val floors: Seq[Floor])
class Floor(val name: String, val bedrooms: Seq[Bedroom]) { var house: House = _}
class Bedroom(val name: String) { var floor: Floor = _ }
/* Factory methods */
def house(floors: Floor*) = {
val house = new House(floors)
floors foreach (_.house = house)
house
}
def floor(name: String)(bedrooms: Bedroom*) = {
val floor = new Floor(name, bedrooms)
bedrooms foreach (_.floor = floor)
floor
}
def bedroom(name: String) = new Bedroom(name)
This allows you to create house structures in a concise and type-safe way as follows:
val myHouse =
house(
floor("first")(
bedroom("joe")
),
floor("second")(
bedroom("anna"),
bedroom("clara")
)
)
assert(myHouse.floors(0).house == myHouse)
assert(myHouse.floors(1).house == myHouse)
assert(myHouse.floors(0).bedrooms(0).floor == myHouse.floors(0))
assert(myHouse.floors(1).bedrooms(1).floor == myHouse.floors(1))
It should be fairly easy to factor out common behaviour into some base traits or methods, for example, iterating over the subcomponents to fix the relationships.