2016-03-23 8 views
0

У нас есть большая система с множеством объектов значений, которые в настоящее время документированы как неизменяемые и которые не предоставляют и методы для мутирования объектов. Переписывая некоторые части кода, я думал, что было бы хорошим упражнением не только документировать классы, чтобы быть неизменными, но и объявлять их неизменными.Объекты неизменяемых значений с вложенными объектами и строителями

Значение объект с вложенным объектом выглядит следующим образом:

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; 
    } 
} 

Всякий раз, когда изменение любых из значений должно быть сделано, мы используем конструктор, чтобы создать копию и изменить атрибуты. Пока все хорошо, но когда дело доходит до вложенных объектов, у меня возникают проблемы. Использование исходного объекта для создания копии из строителя может получить только неизменяемый вложенный объект и сохранить его. Но как строитель может изменить вложенный объект на новый?

Я придумал Rebindable от std.typecons - но я не уверен, что это хорошая практика или нет.

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

Ваше решение с Rebindable в порядке, и я considere его как лучший способ для того чтобы достигнуть этого. Другое возможное решение - сделать nested_ mutable и использовать отливки, но это не так элегантно и безопасно:

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_); 
    } 
}