Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Immutable object
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Language-specific details == In [[Python (programming language)|Python]], [[Java (programming language)|Java]]<ref name=Bloch>{{cite book | title= "Effective Java: Programming Language Guide" |last=Bloch| first=Joshua| publisher=Addison-Wesley | edition=third | isbn=978-0134685991| year=2018}}</ref>{{rp|80}} and the [[.NET Framework]], strings are immutable objects. Both Java and the .NET Framework have mutable versions of string. In Java<ref name=Bloch>{{cite book | title= "Effective Java: Programming Language Guide" |last=Bloch| first=Joshua| publisher=Addison-Wesley | edition=third | isbn=978-0134685991| year=2018}}</ref>{{rp|84}} these are <code>[[StringBuffer]]</code> and <code>[[StringBuilder]]</code> (mutable versions of Java {{Javadoc:SE|java/lang|String}}) and in .NET this is <code>[http://msdn2.microsoft.com/en-us/library/system.text.stringbuilder.aspx StringBuilder]</code> (mutable version of .Net <code>[http://msdn2.microsoft.com/en-us/library/system.string.aspx String]</code>). [[Python 3]] has a mutable string (bytes) variant, named <code>bytearray</code>.<ref>{{cite web|url=https://docs.python.org/release/3.0/library/functions.html#bytearray|title=Built-in Functions β Python v3.0 documentation|website=docs.python.org}}</ref> Additionally, all of the [[primitive wrapper class]]es in Java are immutable. Similar patterns are the [[Immutable interface|Immutable Interface]] and [[Immutable Wrapper]]. In pure [[functional programming]] languages it is not possible to create mutable objects without extending the language (e.g. via a mutable references library or a [[foreign function interface]]), so all objects are immutable. === Ada === In [[Ada (programming language)|Ada]], any object is declared either ''variable'' (i.e. mutable; typically the implicit default), or <code>constant</code> (i.e. immutable) via the <code>constant</code> keyword. <syntaxhighlight lang="ada"> type Some_type is new Integer; -- could be anything more complicated x: constant Some_type:= 1; -- immutable y: Some_type; -- mutable </syntaxhighlight> Subprogram parameters are immutable in the ''in'' mode, and mutable in the ''in out'' and ''out'' modes. <syntaxhighlight lang="ada"> procedure Do_it(a: in Integer; b: in out Integer; c: out Integer) is begin -- a is immutable b:= b + a; c:= a; end Do_it; </syntaxhighlight> === C# === In [[C Sharp (programming language)|C#]] you can enforce immutability of the fields of a class with the <code>readonly</code> statement.<ref name=Skeet>{{cite book |last=Skeet|first=Jon|title= C# in Depth |date=23 March 2019 |publisher= Manning |isbn= 978-1617294532}}</ref>{{rp|239}} By enforcing all the fields as immutable, you obtain an immutable type. <syntaxhighlight lang="csharp"> class AnImmutableType { public readonly double _value; public AnImmutableType(double x) { _value = x; } public AnImmutableType Square() { return new AnImmutableType(_value * _value); } } </syntaxhighlight> C# have records which are immutable.<ref>{{cite web |title=Use record types - C# tutorial - C# |url=https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/records |website=learn.microsoft.com |access-date=23 February 2024 |language=en-us |date=14 November 2023}}</ref><ref>{{cite web |title=Records - C# reference - C# |url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record |website=learn.microsoft.com |access-date=23 February 2024 |language=en-us |date=25 May 2023}}</ref> <syntaxhighlight lang="csharp"> record Person(string FirstName, string LastName); </syntaxhighlight> === C++ === In C++, a [[const-correctness|const-correct]] implementation of <code>Cart</code> would allow the user to create instances of the class and then use them as either <code>const</code> (immutable) or mutable, as desired, by providing two different versions of the <code>items()</code> method. (Notice that in C++ it is not necessary β and in fact impossible β to provide a specialized constructor for <code>const</code> instances.) <syntaxhighlight lang="cpp"> class Cart { public: Cart(std::vector<Item> items): items_(items) {} std::vector<Item>& items() { return items_; } const std::vector<Item>& items() const { return items_; } int ComputeTotalCost() const { /* return sum of the prices */ } private: std::vector<Item> items_; }; </syntaxhighlight> Note that, when there is a data member that is a pointer or reference to another object, then it is possible to mutate the object pointed to or referenced only within a non-const method. C++ also provides abstract (as opposed to bitwise) immutability via the <code>mutable</code> keyword, which lets a [[member variable]] be changed from within a <code>const</code> method. <syntaxhighlight lang="cpp"> class Cart { public: Cart(std::vector<Item> items): items_(items) {} const std::vector<Item>& items() const { return items_; } int ComputeTotalCost() const { if (total_cost_) { return *total_cost_; } int total_cost = 0; for (const auto& item : items_) { total_cost += item.Cost(); } total_cost_ = total_cost; return total_cost; } private: std::vector<Item> items_; mutable std::optional<int> total_cost_; }; </syntaxhighlight> === D === In [[D (programming language)|D]], there exist two [[type qualifier]]s, <code>const</code> and <code>immutable</code>, for variables that cannot be changed.<ref name="d_spec_const">[https://dlang.org/spec/const3.html D Language Specification Β§ 18]</ref> Unlike C++'s <code>const</code>, Java's <code>final</code>, and C#'s <code>readonly</code>, they are transitive and recursively apply to anything reachable through references of such a variable. The difference between <code>const</code> and <code>immutable</code> is what they apply to: <code>const</code> is a property of the variable: there might legally exist mutable references to referred value, i.e. the value can actually change. In contrast, <code>immutable</code> is a property of the referred value: the value and anything transitively reachable from it cannot change (without breaking the type system, leading to [[undefined behavior]]). Any reference of that value must be marked <code>const</code> or <code>immutable</code>. Basically for any unqualified type <code>T</code>, <code>const(T)</code> is the disjoint union of <code>T</code> (mutable) and <code>immutable(T)</code>. <syntaxhighlight lang="d"> class C { /*mutable*/ Object mField; const Object cField; immutable Object iField; } </syntaxhighlight> For a mutable <code>C</code> object, its <code>mField</code> can be written to. For a <code>const(C)</code> object, <code>mField</code> cannot be modified, it inherits <code>const</code>; <code>iField</code> is still immutable as it is the stronger guarantee. For an <code>immutable(C)</code>, all fields are immutable. In a function like this: <syntaxhighlight lang="d"> void func(C m, const C c, immutable C i) { /* inside the braces */ } </syntaxhighlight> Inside the braces, <code>c</code> might refer to the same object as <code>m</code>, so mutations to <code>m</code> could indirectly change <code>c</code> as well. Also, <code>c</code> might refer to the same object as <code>i</code>, but since the value then is immutable, there are no changes. However, <code>m</code> and <code>i</code> cannot legally refer to the same object. In the language of guarantees, mutable has no guarantees (the function might change the object), <code>const</code> is an outward-only guarantee that the function will not change anything, and <code>immutable</code> is a bidirectional guarantee (the function will not change the value and the caller must not change it). Values that are <code>const</code> or <code>immutable</code> must be initialized by direct assignment at the point of [[declaration (computer programming)|declaration]] or by a [[constructor (object-oriented programming)|constructor]]. Because <code>const</code> parameters forget if the value was mutable or not, a similar construct, <code>inout</code>, acts, in a sense, as a variable for mutability information. A function of type <code>const(S) function(const(T))</code> returns <code>const(S)</code> typed values for mutable, const and immutable arguments. In contrast, a function of type <code>inout(S) function(inout(T))</code> returns <code>S</code> for mutable <code>T</code> arguments, <code>const(S)</code> for <code>const(T)</code> values, and <code>immutable(S)</code> for <code>immutable(T)</code> 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."<ref name="d_spec_const"/> 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 <code>string</code> is an alias for <code>immutable(char)[]</code>, i.e. a typed slice of memory of immutable characters.<ref>[https://dlang.org/spec/arrays.html#strings D Language Specification Β§ 12.16] (The terms ''array'' and ''slice'' are used interchangeably.)</ref> 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 <code>const(char)[]</code> 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 (<code>immutable(char[])</code>) returns a string (<code>immutable(char)[]</code>). 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 <code>immutable</code>. It can be stripped by making a depper copy, e.g. using the <code>dup</code> function. === Java === A classic example of an immutable object is an instance of the Java <code>String</code> class <syntaxhighlight lang="java"> String s = "ABC"; s.toLowerCase(); // This accomplishes nothing! </syntaxhighlight> The method <code>toLowerCase()</code> does not change the data "ABC" that <code>s</code> 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 <code>toLowerCase()</code> method. To make the String <code>s</code> contain the data "abc", a different approach is needed: <syntaxhighlight lang="java"> s = s.toLowerCase(); </syntaxhighlight> Now the String <code>s</code> 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 <code>final</code> ([[Final (Java)#Final variables|detailed article]]) is used in implementing immutable primitive types and object references,<ref>{{cite web|url=http://javarevisited.blogspot.co.uk/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html |title=How to create Immutable Class and Object in Java β Tutorial Example |publisher=Javarevisited.blogspot.co.uk |date=2013-03-04 |access-date=2014-04-14}}</ref> but it cannot, by itself, make ''the objects themselves'' immutable. See below examples: Primitive type variables (<code>int</code>, <code>long</code>, <code>short</code>, etc.) can be reassigned after being defined. This can be prevented by using <code>final</code>. <syntaxhighlight lang="java"> 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 </syntaxhighlight> Reference types cannot be made immutable just by using the <code>final</code> keyword. <code>final</code> only prevents reassignment. <syntaxhighlight lang="java"> final MyObject m = new MyObject(); //m is of reference type m.data = 100; // OK. We can change state of object m (m is mutable and final doesn't change this fact) m = new MyObject(); // does not compile. m is final so can't be reassigned </syntaxhighlight> Primitive wrappers (<code>Integer</code>, <code>Long</code>, <code>Short</code>, <code>Double</code>, <code>Float</code>, <code>Character</code>, <code>Byte</code>, <code>Boolean</code>) are also all immutable. Immutable classes can be implemented by following a few simple guidelines.<ref>{{cite web | url=http://www.javapractices.com/topic/TopicAction.do?Id=29 | title=Immutable objects | publisher=javapractices.com | access-date=November 15, 2012}}</ref> === JavaScript === In [[JavaScript]], all primitive types (Undefined, Null, Boolean, Number, BigInt, String, Symbol) are immutable, but custom objects are generally mutable. <syntaxhighlight lang="javascript"> function doSomething(x) { /* does changing x here change the original? */ }; var str = 'a string'; var obj = { an: 'object' }; doSomething(str); // strings, numbers and bool types are immutable, function gets a copy doSomething(obj); // objects are passed in by reference and are mutable inside function doAnotherThing(str, obj); // `str` has not changed, but `obj` may have. </syntaxhighlight> To simulate immutability in an object, one may define properties as read-only (writable: false). <syntaxhighlight lang="javascript"> var obj = {}; Object.defineProperty(obj, 'foo', { value: 'bar', writable: false }); obj.foo = 'bar2'; // silently ignored </syntaxhighlight> However, the approach above still lets new properties be added. Alternatively, one may use [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze Object.freeze] to make existing objects immutable. <syntaxhighlight lang="javascript"> var obj = { foo: 'bar' }; Object.freeze(obj); obj.foo = 'bars'; // cannot edit property, silently ignored obj.foo2 = 'bar2'; // cannot add property, silently ignored </syntaxhighlight> With the implementation of [https://tc39.es/ecma262/#sec-let-and-const-declarations ECMA262], JavaScript has the ability to create immutable references that cannot be reassigned. However, using a <code>const</code> declaration doesn't mean that value of the read-only reference is immutable, just that the name cannot be assigned to a new value. <syntaxhighlight lang="javascript"> const ALWAYS_IMMUTABLE = true; try { ALWAYS_IMMUTABLE = false; } catch (err) { console.log("Can't reassign an immutable reference."); } const arr = [1, 2, 3]; arr.push(4); console.log(arr); // [1, 2, 3, 4] </syntaxhighlight> The use of immutable state has become a rising trend in JavaScript since the introduction of [[React (JavaScript library)|React]], which favours Flux-like state management patterns such as [[Redux (JavaScript library)|Redux]].<ref>{{cite web|title=Immutability in JavaScript: A Contrarian View|url=http://desalasworks.com/article/immutability-in-javascript-a-contrarian-view/|website=Desalasworks}}</ref> === Perl === In [[Perl]], one can create an immutable class with the Moo library by simply declaring all the attributes read only: <syntaxhighlight lang="perl"> package Immutable; use Moo; has value => ( is => 'ro', # read only default => 'data', # can be overridden by supplying the constructor with # a value: Immutable->new(value => 'something else'); ); 1; </syntaxhighlight> Creating an immutable class used to require two steps: first, creating accessors (either automatically or manually) that prevent modification of object attributes, and secondly, preventing direct modification of the instance data of instances of that class (this was usually stored in a hash reference, and could be locked with Hash::Util's lock_hash function): <syntaxhighlight lang="perl"> package Immutable; use strict; use warnings; use base qw(Class::Accessor); # create read-only accessors __PACKAGE__->mk_ro_accessors(qw(value)); use Hash::Util 'lock_hash'; sub new { my $class = shift; return $class if ref($class); die "Arguments to new must be key => value pairs\n" unless (@_ % 2 == 0); my %defaults = ( value => 'data', ); my $obj = { %defaults, @_, }; bless $obj, $class; # prevent modification of the object data lock_hash %$obj; } 1; </syntaxhighlight> Or, with a manually written accessor: <syntaxhighlight lang="perl"> package Immutable; use strict; use warnings; use Hash::Util 'lock_hash'; sub new { my $class = shift; return $class if ref($class); die "Arguments to new must be key => value pairs\n" unless (@_ % 2 == 0); my %defaults = ( value => 'data', ); my $obj = { %defaults, @_, }; bless $obj, $class; # prevent modification of the object data lock_hash %$obj; } # read-only accessor sub value { my $self = shift; if (my $new_value = shift) { # trying to set a new value die "This object cannot be modified\n"; } else { return $self->{value} } } 1; </syntaxhighlight> === PHP === In [[PHP]] have readonly properties since version 8.1 and readonly classes since version 8.2.<ref>https://www.php.net/releases/8.1/en.php#readonly_properties</ref><ref>https://www.php.net/releases/8.2/en.php#readonly_classes</ref> <syntaxhighlight lang="php"> readonly class BlogData { public string $title; public Status $status; public function __construct(string $title, Status $status) { $this->title = $title; $this->status = $status; } } </syntaxhighlight> === Python === In [[Python (programming language)|Python]], some built-in types (numbers, Booleans, strings, tuples, frozensets) are immutable, but custom classes are generally mutable. To simulate immutability in a class, one could override attribute setting and deletion to raise exceptions: <syntaxhighlight lang="python"> class ImmutablePoint: """An immutable class with two attributes 'x' and 'y'.""" __slots__ = ['x', 'y'] def __setattr__(self, *args): raise TypeError("Can not modify immutable instance.") __delattr__ = __setattr__ def __init__(self, x, y): # We can no longer use self.value = value to store the instance data # so we must explicitly call the superclass super().__setattr__('x', x) super().__setattr__('y', y) </syntaxhighlight> The standard library helpers [https://docs.python.org/3/library/collections.html#collections.namedtuple <code>collections.namedtuple</code>] and [https://docs.python.org/3/library/typing.html#typing.NamedTuple <code>typing.NamedTuple</code>], available from Python 3.6 onward, create simple immutable classes. The following example is roughly equivalent to the above, plus some tuple-like features: <syntaxhighlight lang="python"> from typing import NamedTuple import collections Point = collections.namedtuple('Point', ['x', 'y']) # the following creates a similar namedtuple to the above class Point(NamedTuple): x: int y: int </syntaxhighlight> Introduced in Python 3.7, [https://docs.python.org/3/library/dataclasses.html <code>dataclasses</code>] allow developers to emulate immutability with [https://docs.python.org/3/library/dataclasses.html#frozen-instances frozen instances]. If a frozen dataclass is built, <code>dataclasses</code> will override <code>__setattr__()</code> and <code>__delattr__()</code> to raise <code>FrozenInstanceError</code> if invoked. <syntaxhighlight lang="python"> from dataclasses import dataclass @dataclass(frozen=True) class Point: x: int y: int </syntaxhighlight> === Racket === [[Racket (programming language)|Racket]] substantially diverges from other [[Scheme (programming language)|Scheme]] implementations by making its core pair type ("cons cells") immutable. Instead, it provides a parallel mutable pair type, via <code>mcons</code>, <code>mcar</code>, <code>set-mcar!</code> 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: <syntaxhighlight lang="racket"> (struct foo1 (x y)) ; all fields immutable (struct foo2 (x [y #:mutable])) ; one mutable field (struct foo3 (x y) #:mutable) ; all fields mutable </syntaxhighlight> The language also supports immutable hash tables, implemented functionally, and immutable dictionaries. === Rust === Rust's [[Rust (programming language)#Ownership|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 <code>mut</code> keyword. [https://doc.rust-lang.org/reference/items/constant-items.html Constant items] in Rust are always immutable. <syntaxhighlight lang="rust"> // constant items are always immutable const ALWAYS_IMMUTABLE: bool = true; struct Object { x: usize, y: usize, } fn main() { // explicitly declare a mutable variable let mut mutable_obj = Object { x: 1, y: 2 }; mutable_obj.x = 3; // okay let mutable_ref = &mut mutable_obj; mutable_ref.x = 1; // okay let immutable_ref = &mutable_obj; immutable_ref.x = 3; // error E0594 // by default, variables are immutable let immutable_obj = Object { x: 4, y: 5 }; immutable_obj.x = 6; // error E0596 let mutable_ref2 = &mut immutable_obj; // error E0596 let immutable_ref2 = &immutable_obj; immutable_ref2.x = 6; // error E0594 } </syntaxhighlight> === Scala === In [[Scala (programming language)|Scala]], any entity (narrowly, a binding) can be defined as mutable or immutable: in the declaration, one can use <code>val</code> (value) for immutable entities and <code>var</code> (variable) 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: <syntaxhighlight lang="scala"> val maxValue = 100 var currentValue = 1 </syntaxhighlight> defines an immutable entity <code>maxValue</code> (the integer type is inferred at compile-time) and a mutable entity named <code>currentValue</code>. By default, collection classes such as <code>List</code> and <code>Map</code> 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.<ref>{{cite web|url=http://www.scala-lang.org/docu/files/collections-api/collections_12.html |title=Scala 2.8 Collections API β Concrete Immutable Collection Classes |publisher=Scala-lang.org |access-date=2014-04-14}}</ref>{{Better source|reason=This is a controversial (and vague) claim, so should be supported by a source other than the Scala foundation itself.|date=July 2017}}
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)