Scala DSL - Nested block referencing parent

后端 未结 2 1436
慢半拍i
慢半拍i 2021-01-19 19:30

Playing about with a DSL in Scala, so lets say I have something like this:

house {
  floor {
    bedroom(\"kids)
    bedroom(\"master\")
  }
  floor {
    ki         


        
2条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-19 20:20

    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.

提交回复
热议问题