0.5.0 - Support for the decorator pattern / wrappers
With this release, it becomes possible to have the mutability of a decorator/wrapper depend on the mutability of the object it wraps. If you decorate a const object, the decorator is automatically const, and likewise for mut.
To make use of this, declare the member variable that holds the decorated/wrapped object as decorates:
interface NumberHolder {
get fn n(self) -> U32
set fn n(self: mut _, v: U32)
}
class SimpleNumberHolder : NumberHolder {
private var _n: U32 = init
override get fn n(self) = self._n
override set fn n(self: mut _, v: U32) {
set self._n = v
}
}
class MultiplyBy4NumberHolder : NumberHolder {
decorates private delegate: NumberHolder = init
override get fn n(self) -> U32 {
// here, self.delegate is a read NumberHolder, because the self reference is read, too
return self.delegate.n * 4
}
override set fn n(self: mut _, v: U32) {
if v.rem(4) != 0 {
panic("must be a multiple of 4!")
}
// however, here self.delegate is mut because the decorator reference (self) is mut
set self.delegate.n = v / 4
}
}
fn example1() {
var simple = SimpleNumberHolder(1)
decorated: const MultiplyBy4NumberHolder(simple) // error: simple is mutable, the decorator is also mutable, not assignable to const
}
fn example2() {
var mutDecorated: mut _ = MultiplyBy4NumberHolder(SimpleNumberHolder(1)) // works; exclusive nested object can be mut
constDecorated: const _ = MultiplyBy4NumberHolder(SimpleNumberHolder(2)) // works, too: exclusive nested object can be const
}
This can not yet be combined with secondary constructors effectively, though.