Construction Through Composition

In this construction, having access to the resource means having access to all of its capabilities, because the resource implements the capabilities directly as traits.

Before

sourceobject Before {

  final class Document(var name: String) {
    override def toString: String = s"Document($name)"
  }

  def main(args: Array[String]): Unit = {
    val document = new Document("will")
    document.name = "steve"
    println(s"Before: result = $document")
  }
}

After

sourceobject AfterAttenuation {

  final class Document(private var name: String) extends Document.NameChanger {
    override def changeName(newName: String): Unit = {
      name = newName
    }
    override def toString: String = s"Document($name)"
  }

  object Document {
    trait NameChanger {
      def changeName(name: String): Unit
    }
  }

  def main(args: Array[String]): Unit = {
    val document = new Document("will")

    // expose a single facet through attenuation
    val nameChanger = new Document.NameChanger {
      override def changeName(name: String): Unit = document.changeName(name)
    }
    nameChanger.changeName("steve")
    println(s"AfterAttenuation: result = $document")
  }
}
The source code for this page can be found here.