我们有一个包含大量值对象的大型系统,这些对象目前被记录为不可变的,并且没有提供和改变对象的方法。在重写代码的某些部分时,我认为不仅要将类记录为不可变,而且将它们声明为不可变,这将是一个很好的练习。
具有嵌套对象的Value对象如下所示:
immutable class Nested
{
int i;
public this(int i) immutable
{
this.i = i;
}
}
immutable class Value
{
private Nested nested_;
public immutable(Nested) nested() const
{
return this.nested_;
}
package this(immutable(Nested) nested)
{
this.nested_ = nested;
}
}
每当需要对任何值进行更改时,我们使用构建器来创建副本并修改属性。到目前为止一切都很好 - 但是当谈到嵌套对象时,我遇到了麻烦。使用原始对象从构建器创建副本只能获取不可变嵌套对象并存储它。但是构建器如何将嵌套对象更改为新对象?
我从std.typecons想出了Rebindable - 但我不确定这是否是好习惯。
class Builder
{
import std.typecons : Rebindable;
Rebindable!(immutable(Nested)) nested_;
this()
{
this.nested_ = null;
}
this(immutable(Value) value)
{
this.nested_ = value.nested;
}
public void nested(immutable(Nested) nested)
{
this.nested_ = nested;
}
public immutable(Value) value() const
{
return new immutable Value(this.nested_);
}
}
void main()
{
import std.stdio : writefln;
immutable value = new immutable Value(new immutable Nested(1));
writefln("i = %d", value.nested.i);
auto builder = new Builder(value);
immutable newNested = new immutable Nested(2);
builder.nested = newNested;
writefln("i = %d", builder.value.nested.i);
}
我是否在考虑不变性和常规正确性?
此致
鲁尼
答案 0 :(得分:0)
您使用Rebindable
的解决方案是可以的,我认为这是实现这一目标的最佳方式。另一个可能的解决方案是使嵌套_可变并使用强制转换,但这不是那么优雅和安全:
class Builder
{
import std.typecons : Rebindable;
union
{
private Nested m_nested_;
immutable(Nested) nested_;
}
this()
{
this.nested_ = null;
}
this(immutable(Value) value)
{
this.nested_ = value.nested();
}
public void nested(immutable(Nested) nested)
{
this.m_nested_ = cast(Nested)nested;
}
public immutable(Value) value() const
{
return new immutable Value(this.nested_);
}
}