简体   繁体   中英

For an object in scala to be immutable what is required?

Is the answer to this :

Instantiation of the object uses 'val' instead of 'var'.

Each member variable of the object being created is also 'val' instead of 'var'. This is to prevent users updating an object value after its set.

An object is immutable if there is no way for the user of that object to mutate it. This means that it must have no public methods that reassign any of its member variables or mutate any objects referred to by those variables. If all the object's members are val s this ensures the former (ie they can't be reassigned), but not the latter (ie if the objects referred to by those variables are themselves mutable, they can still be mutated by calling mutating methods on them even if they're referred to only by val s).

Also note that even if the members are declared as var s, the object can still be immutable if none of the object's methods actually reassign the variables (or call mutating methods on them) - assuming of course, they're private.

So having only val members is neither necessary nor sufficient for an object being immutable. Whether the object is referred to by a val or a var (or both) makes no difference in that matter.

@sepp2k nicely and correctly explains the criteria for an object being technically immutable. One subtle point missing from his answer is that not all member variables correspond to externally visible state . A member may also be eg a cached internal value to store some local, hard to compute data which is not directly visible from outside (thus qualified as private[this] in Scala). An object can have such a var member eg to store a computed hash value. It can even be accessible via a public getter - as long as the behaviour of the accessor is purely functional, ie it always produces the same value for each invocation on the same object (except that it returns faster when reusing the internally cached value).

The Scala compiler is aware of this distinction so it can help one to implement an immutable class correctly, even when using mutable state internally. This is important when generic type variance comes into play. Namely, the compiler allows a generic type parameter to be covariant even if the class contains reassignable fields of this type - as long as these fields are private[this] , ensuring that one cannot have a reference to a containing object that has a statically weaker type than the type the object was defined with (which would be a precondition for variance to cause type errors).

This is explained in more detail, with a code example, in section 19.7 of Programming in Scala .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM