Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Immutable only class in D

Tags:

d

How do I make an immutable class?

My goal is to make a class whose instances are always immutable. Right now I just make a "mutable" class with immutable methods and constructors only. I'll call it mData, m for mutable. Then I make an alias alias immutable(mData) Data; and use it everywhere instead of the class name. This works well, but seems unnecessary.

If I label the class definition with immutable (immutable class Data{...}), that doesn't follow the class use around. So if I used it from another class or function and call an immutable method (they all are) the compiler complains about calling an immutable method on a mutable object, even though by definition the class is immutable! To get around this, I have to add the immutable keyword in front of the type name everywhere. Which is what the alias was really doing for me.

Is the alias really the best way to do this? What does the immutable key word do for a class definition? If it does nothing shouldn't this be a warning or error of some kind?

(Using Xamarin Studio with dub and DMD32 D Compiler v2.066.0 on Windows 8)

like image 553
Ryan Avatar asked Dec 06 '14 23:12

Ryan


1 Answers

I think alias is the best way to do it, coupled with the immutable outside the class. What the latter does is:

http://dlang.org/class.html If a ClassDeclaration has a const, immutable or shared storage class, then it is as if each member of the class was declared with that storage class. If a base class is const, immutable or shared, then all classes derived from it are also const, immutable or shared.

So it saves you from setting immutable on everything inside and also applies to inheritance. But it doesn't change the type itself - Data is still a mutable reference, just to all immutable data (which btw might be useful at times, because it can be easily rebinded to another instance). Your alias achieves the whole change in type.

BTW, also add a constructor to your immutable class. Even if it is just empty, the presence of an immutable constructor (which would be all if you put immutable on the outside) will forbid mutable construction entirely:

immutable class Foo { }

Foo foo = new Foo(); // permitted. All the data will be immutable, but it will let you construct it this way

immutable class Foo {
    this() {} 
}         

Foo foo = new Foo(); // Error: immutable method test100.Foo.this is not callable using a mutable object

So then you'd want to construct it with

auto foo = new immutable Foo(); // (infers based on right hand side)

You could also write it as:

immutable foo = new immutable Foo(); // (infers always to an immutable type)

or

immutable(Foo) foo = new immutable Foo(); // (explicitly writing the immutable type)

depending on what you prefer.

like image 182
Adam D. Ruppe Avatar answered Oct 16 '22 13:10

Adam D. Ruppe