Immutable object


In object-oriented and functional programming, an immutable object is an object whose state cannot be modified after it is created. This is in contrast to a mutable object, which can be modified after it is created. In some cases, an object is considered immutable even if some internally used attributes change, but the object's state appears unchanging from an external point of view. For example, an object that uses memoization to cache the results of expensive computations could still be considered an immutable object.
Strings and other concrete objects are typically expressed as immutable objects to improve readability and runtime efficiency in object-oriented programming. Immutable objects are also useful because they are inherently thread-safe. Other benefits are that they are simpler to understand and reason about and offer higher security than mutable objects.

Concepts

Immutable variables

In imperative programming, values held in program variables whose content never changes are known as constants to differentiate them from variables that could be altered during execution. Examples include conversion factors from meters to feet, or the value of pi to several decimal places.
Read-only fields may be calculated when the program runs, but never change after they are initialized.

Weak vs strong immutability

Sometimes, one talks of certain fields of an object being immutable. This means that there is no way to change those parts of the object state, even though other parts of the object may be changeable. If all fields are immutable, then the object is immutable. If the whole object cannot be extended by another class, the object is called strongly immutable. This might, for example, help to explicitly enforce certain invariants about certain data in the object staying the same through the lifetime of the object. In some languages, this is done with a keyword that designates the field as immutable. Some languages reverse it: in OCaml, fields of an object or record are by default immutable, and must be explicitly marked with mutable to be so.

Referencing vs copying objects

If an object is known to be immutable, it is preferred to create a reference of it instead of copying the entire object. This is done to conserve memory by preventing data duplication and avoid calls to constructors and destructors; it also results in a potential boost in execution speed.
The reference copying technique is much more difficult to use for mutable objects, because if any user of a mutable object reference changes it, all other users of that reference see the change. If this is not the intended effect, it can be difficult to notify the other users to have them respond correctly. In these situations, defensive copying of the entire object rather than the reference is usually an easy but costly solution. The observer pattern is an alternative technique for handling changes to mutable objects.

Copy-on-write

A technique that blends the advantages of mutable and immutable objects, and is supported directly in almost all modern hardware, is copy-on-write. Using this technique, when a user asks the system to copy an object, it instead merely creates a new reference that still points to the same object. As soon as a user attempts to modify the object through a particular reference, the system makes a real copy, applies the modification to that, and sets the reference to refer to the new copy. The other users are unaffected, because they still refer to the original object. Therefore, under COW, all users appear to have a mutable version of their objects, although in the case that users do not modify their objects, the space-saving and speed advantages of immutable objects are preserved. Copy-on-write is popular in virtual memory systems because it allows them to save memory space while still correctly handling anything an application program might do.

Interning

The practice of always using references in place of copies of equal objects is known as interning. If interning is used, two objects are considered equal if and only if their references, typically represented as pointers or integers, are equal. Some languages do this automatically: for example, Python automatically interns short strings. If the algorithm that implements interning is guaranteed to do so in every case that it is possible, then comparing objects for equality is reduced to comparing their pointers – a substantial gain in speed in most applications. Interning is generally only useful for immutable objects.

Thread safety

Immutable objects can be useful in multi-threaded applications. Multiple threads can act on data represented by immutable objects without concern of the data being changed by other threads. Immutable objects are therefore considered more thread-safe than mutable objects.

Violating immutability

Immutability does not imply that the object as stored in the computer's memory is unwriteable. Rather, immutability is a compile-time construct that indicates what a programmer can do through the normal interface of the object, not necessarily what they can absolutely do.

Language-specific details

In Python, Java and the.NET Framework, strings are immutable objects. Both Java and the.NET Framework have mutable versions of string. In Java these are StringBuffer and StringBuilder and in.NET this is . Python 3 has a mutable string variant, named bytearray.
Additionally, all of the primitive wrapper classes in Java are immutable.
Similar patterns are the Immutable Interface and Immutable Wrapper.
In pure functional programming languages it is not possible to create mutable objects without extending the language, so all objects are immutable.

Ada

In Ada, any object is declared either variable, or constant via the constant keyword.

type Some_type is new Integer; -- could be anything more complicated
x: constant Some_type:= 1; -- immutable
y: Some_type; -- mutable

Subprogram parameters are immutable in the in mode, and mutable in the in out and out modes.

procedure Do_it is
begin
-- a is immutable
b:= b + a;
c:= a;
end Do_it;

C#

In C# you can enforce immutability of the fields of a class with the readonly statement.
By enforcing all the fields as immutable, you obtain an immutable type.

class AnImmutableType

C++

In C++, a const-correct implementation of Cart would allow the user to declare new instances of the class as either const or mutable, as desired, by providing two different versions of the getItems method.

class Cart ;

Note that, if there were a field that is a pointer or reference to another object, then it might still be possible to mutate the object pointed to by such a pointer or reference within a const method, without violating const-correctness. It can be argued that in such a case the object is not really immutable.
C++ also provides abstract immutability via the mutable keyword, which lets a member variable be changed from within a const method.

class Cart ;

D

In D, there exist two type qualifiers, const and immutable, for variables that cannot be changed. Unlike C++'s const, Java's final, and C#'s readonly, they are transitive and recursively apply to anything reachable through references of such a variable. The difference between const and immutable is what they apply to: const is a property of the variable: there might legally exist mutable references to referred value, i.e. the value can actually change. In contrast, immutable is a property of the referred value: the value and anything transitively reachable from it cannot change. Any reference of that value must be marked const or immutable. Basically for any unqualified type T, const is the disjoint union of T and immutable.

class C

For a mutable C object, its mField can be written to. For a const object, mField cannot be modified, it inherits const; iField is still immutable as it is the stronger guarantee. For an immutable, all fields are immutable.
In a function like this:

void func

Inside the braces, c might refer to the same object as m, so mutations to m could indirectly change c as well. Also,
c might refer to the same object as i, but since the value then is immutable, there are no changes. However, m and i cannot legally refer to the same object.
In the language of guarantees, mutable has no guarantees, const is an outward-only guarantee that the function will not change anything, and
immutable is a bidirectional guarantee.
Values that are const or immutable must be initialized by direct assignment at the point of declaration or by a constructor.
Because const parameters forget if the value was mutable or not, a similar construct, inout, acts, in a sense, as a variable for mutability information.
A function of type const function returns const typed values for mutable, const and immutable arguments. In contrast, a function of type inout function returns S for mutable T arguments, const for const values, and immutable for immutable values.
Casting immutable values to mutable inflicts undefined behavior upon change, even if the original value comes from a mutable origin. Casting mutable values to immutable can be legal when there remain no mutable references afterward. "An expression may be converted from mutable to immutable if the expression is unique and all expressions it transitively refers to are either unique or immutable." If the compiler cannot prove uniqueness, the casting can be done explicitly and it is up to the programmer to ensure that no mutable references exist.
The type string is an alias for immutable, i.e. a typed slice of memory of immutable characters. Making substrings is cheap, as it just copies and modifies a pointer and a length filed, and safe, as the underlying data cannot be changed. Objects of type const can refer to strings, but also to mutable buffers.
Making a shallow copy of a const or immutable value removes the outer layer of immutability: Copying an immutable string returns a string. The immutable pointer and length are being copied and the copies are mutable. The referred data has not been copied and keeps its qualifier, in the example immutable. It can be stripped by making a depper copy, e.g. using the dup function.

Java

A classic example of an immutable object is an instance of the Java String class

String s = "ABC";
s.toLowerCase;

The method toLowerCase does not change the data "ABC" that s contains. Instead, a new String object is instantiated and given the data "abc" during its construction. A reference to this String object is returned by the toLowerCase method. To make the String s contain the data "abc", a different approach is needed:

s = s.toLowerCase;

Now the String s references a new String object that contains "abc". There is nothing in the syntax of the declaration of the class String that enforces it as immutable; rather, none of the String class's methods ever affect the data that a String object contains, thus making it immutable.
The keyword final is used in implementing immutable primitive types and object references, but it cannot, by itself, make the objects themselves immutable. See below examples:
Primitive type variables can be reassigned after being defined. This can be prevented by using final.

int i = 42; //int is a primitive type
i = 43; // OK
final int j = 42;
j = 43; // does not compile. j is final so can't be reassigned

Reference types cannot be made immutable just by using the final keyword. final only prevents reassignment.

final MyObject m = new MyObject; //m is of reference type
m.data = 100; // OK. We can change state of object m
m = new MyObject; // does not compile. m is final so can't be reassigned

Primitive wrappers are also all immutable. Immutable classes can be implemented by following a few simple guidelines.

Perl

In Perl, one can create an immutable class with the Moo library by simply declaring all the attributes read only:

package Immutable;
use Moo;
has value => ;
1;

Creating an immutable class used to require two steps: first, creating accessors that prevent modification of object attributes, and secondly, preventing direct modification of the instance data of instances of that class :

package Immutable;
use strict;
use warnings;
use base qw;
  1. create read-only accessors
__PACKAGE__->mk_ro_accessors;
use Hash::Util 'lock_hash';
sub new
1;

Or, with a manually written accessor:

package Immutable;
use strict;
use warnings;
use Hash::Util 'lock_hash';
sub new
  1. read-only accessor
sub value
1;

Python

In Python, some built-in types are immutable, but custom classes are generally mutable. To simulate immutability in a class, one could override attribute setting and deletion to raise exceptions:

class ImmutablePoint:
"""An immutable class with two attributes 'x' and 'y'."""
__slots__ =
def __setattr__:
raise TypeError
__delattr__ = __setattr__
def __init__:
# We can no longer use self.value = value to store the instance data
# so we must explicitly call the superclass
super.__setattr__
super.__setattr__

The standard library helpers and , available from Python 3.6 onward, create simple immutable classes. The following example is roughly equivalent to the above, plus some tuple-like features:

from typing import NamedTuple
import collections
Point = collections.namedtuple
  1. the following creates a similar namedtuple to the above
class Point:
x: int
y: int

Introduced in Python 3.7, allow developers to emulate immutability with . If a frozen dataclass is built, dataclasses will override __setattr__ and __delattr__ to raise FrozenInstanceError if invoked.

from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int

JavaScript

In JavaScript, all primitive types are immutable, but custom objects are generally mutable.

function doSomething ;
var str = 'a string';
var obj = ;
doSomething; // strings, numbers and bool types are immutable, function gets a copy
doSomething; // objects are passed in by reference and are mutable inside function
doAnotherThing; // `str` has not changed, but `obj` may have.

To simulate immutability in an object, one may define properties as read-only.

var obj = ;
Object.defineProperty;
obj.foo = 'bar2'; // silently ignored

However, the approach above still lets new properties be added. Alternatively, one may use to make existing objects immutable.

var obj = ;
Object.freeze;
obj.foo = 'bars'; // cannot edit property, silently ignored
obj.foo2 = 'bar2'; // cannot add property, silently ignored

With the implementation of , JavaScript has the ability to create immutable references that cannot be reassigned. However, using a const declaration doesn't mean that value of the read-only reference is immutable, just that the name cannot be assigned to a new value.

const ALWAYS_IMMUTABLE = true;
try catch
const arr = ;
arr.push;
console.log; //

The use of immutable state has become a rising trend in JavaScript since the introduction of React, which favours Flux-like state management patterns such as Redux.

Racket

substantially diverges from other Scheme implementations by making its core pair type immutable. Instead, it provides a parallel mutable pair type, via mcons, mcar, set-mcar! etc. In addition, many immutable types are supported, for example, immutable strings and vectors, and these are used extensively. New structs are immutable by default, unless a field is specifically declared mutable, or the whole struct:

; all fields immutable
; one mutable field
; all fields mutable

The language also supports immutable hash tables, implemented functionally, and immutable dictionaries.

Rust

Rust's ownership system allows developers to declare immutable variables, and pass immutable references. By default, all variables and references are immutable. Mutable variables and references are explicitly created with the mut keyword.
in Rust are always immutable.

// constant items are always immutable
const ALWAYS_IMMUTABLE: bool = true;
struct Object
fn main

Scala

In Scala, any entity can be defined as mutable or immutable: in the declaration, one can use val for immutable entities and var for mutable ones. Note that even though an immutable binding can not be reassigned, it may still refer to a mutable object and it is still possible to call mutating methods on that object: the binding is immutable, but the underlying object may be mutable.
For example, the following code snippet:

val maxValue = 100
var currentValue = 1

defines an immutable entity maxValue and a mutable entity named currentValue.
By default, collection classes such as List and Map are immutable, so update-methods return a new instance rather than mutating an existing one. While this may sound inefficient, the implementation of these classes and their guarantees of immutability mean that the new instance can re-use existing nodes, which, especially in the case of creating copies, is very efficient.