Construction Through Access

The most flexible way to set up capabilities from resources is to set up a resource with private methods that are then exposed through an Access class in a companion object which has sibling privileges to the capabilities.

You can read more in Constructing Capabilities section of the guide.

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 AfterAmplification {

  final class Document(private var name: String) {
    private object capabilities {
      val nameChanger = new 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
    }

    class Access {
      def nameChanger(doc: Document): NameChanger = {
        doc.capabilities.nameChanger
      }
    }
  }

  def main(args: Array[String]): Unit = {
    val document = new Document("will")
    val access = new Document.Access()
    val nameChanger = access.nameChanger(document)
    nameChanger.changeName("steve")
    println(s"AfterAmplification: result = $document")
  }
}
The source code for this page can be found here.