Content deleted Content added
Tags: Mobile edit Mobile web edit |
|||
(40 intermediate revisions by 26 users not shown) | |||
Line 1:
{{short description|Object whose state cannot be modified after it is created}}
{{Redirect2|Immutable|Immutability|the Christian doctrine|Immutability (theology)|the album|Immutable (album)|the crypto gaming company|Immutable Pty Ltd}}
In [[object-oriented computer programming|object-oriented]] (OO) and [[Functional programming|functional]] programming, an '''immutable object''' (unchangeable<ref>{{cite web|url=http://www.oxfordlearnersdictionaries.com/definition/english/immutable|title=immutable adjective - Definition, pictures, pronunciation and usage notes - Oxford Advanced Learner's Dictionary at OxfordLearnersDictionaries.com|website=www.oxfordlearnersdictionaries.com}}</ref> object) is an [[object (computer science)|object]] whose [[State (computer science)|state]] cannot be modified after it is created.<ref name=Goetz>Goetz et al. ''Java Concurrency in Practice''. Addison Wesley Professional, 2006, Section 3.4. Immutability</ref> This is in contrast to a '''mutable object''' (changeable object), which can be modified after it is created.<ref>{{cite web|url=https://web.mit.edu/6.005/www/fa16/classes/09-immutability/|title=6.005 — Software Construction}}</ref> 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 <!--
YES, THIS IS SPELLED CORRECTLY. IT'S *NOT* "memo*r*ization". READ THE LINKED ARTICLE.
-->{{Not a typo|[[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
== Concepts ==
Line 21 ⟶ 22:
| date = April 2003
| work = Java Ranch
| quote = The preferred way is to make the class final. This is sometimes referred to as "Strong Immutability". It prevents anyone from extending your class and accidentally or deliberately making it mutable.
|
}}</ref> 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 (e.g. <code>const</code> in [[C++]], <code>final</code> in [[Java (programming language)|Java]]) 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 <code>mutable</code> to be so.
Line 38:
=== Interning ===
The practice of always using references in place of copies of equal objects is known as ''[[intern (computer science)|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 (programming language)|Python]] automatically [[String intern pool|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. (Even if the algorithm is not guaranteed to be comprehensive, there still exists the possibility of a [[fast path]] case improvement when the objects are equal and use the same reference.) Interning is generally only useful for immutable objects.
=== Thread safety ===
Line 44:
=== Violating immutability ===
Immutability does not imply that the object as stored in the computer's [[Computer storage|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 (for instance, by circumventing the [[type system]] or violating [[const correctness]] in [[C (programming language)|C]] or [[C++]]).
== 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.
Line 73:
=== 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="
class AnImmutableType
{
Line 89:
}
}
</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>
<syntaxhighlight lang="cpp">
class
private:
public:
explicit Cart(std::vector<Item> items):
items{items} {}
std::vector<
}
const std::vector<Item>& items() const {
return items;
}
double computeTotalCost() const {
return std::ranges::accumulate(
items | std::views::transform([](const Merchandise& m) -> double { return m.getPrice(); }), 0.0
);
}
};
</syntaxhighlight>
Note that,
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
private:
mutable std::optional<int> totalCost;
public:
explicit Cart(std::vector<Merchandise> items): items{items} {}
const std::vector<
return }
int
totalCost = std::ranges::accumulate(
items | std::views::transform([](const Merchandise& m) -> double { return m.getPrice(); }), 0.0
);
}
return *totalCost;
}
};
</syntaxhighlight>
Line 170 ⟶ 181:
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.
Line 181 ⟶ 192:
<syntaxhighlight lang="java">
String s = "ABC";
s.toLowerCase(); // This accomplishes nothing!
</syntaxhighlight>
Line 192 ⟶ 203:
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 |
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>.
Line 210 ⟶ 221:
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 |
=== 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 ===
Line 289 ⟶ 347:
}
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,
<syntaxhighlight lang="python">
Line 298 ⟶ 374:
"""An immutable class with two attributes 'x' and 'y'."""
__slots__ = [
def __setattr__(self, *args):
Line 308 ⟶ 384:
# We can no longer use self.value = value to store the instance data
# so we must explicitly call the superclass
super().__setattr__(
super().__setattr__(
</syntaxhighlight>
Line 318 ⟶ 394:
import collections
Point = collections.namedtuple(
# the following creates a similar namedtuple to the above
Line 336 ⟶ 412:
y: int
</syntaxhighlight>
=== Racket ===
Line 441 ⟶ 470:
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
== See also ==
Line 448 ⟶ 477:
* [[F Sharp (programming language)|F#]]
* [[Haskell (programming language)|Haskell]]
*[[Mutator method]]
* [[Prolog]]
*[[Scala (programming language)|Scala]]
* [[Tcl]]
== References ==
Line 460 ⟶ 489:
{{Wiktionary|mutable}}
* [https://www.codeproject.com/Articles/1043301/Immutable-objects-in-Csharp Immutable objects in C#] using 3 simple steps.
* Article [https://web.archive.org/web/20101020235317/http://www.ibm.com/developerworks/java/library/j-jtp02183.html Java theory and practice: To mutate or not to mutate?] by [[Brian Goetz]], from
* [http://www.javapractices.com/Topic29.cjp Immutable objects] from JavaPractices.com
* [http://c2.com/cgi/wiki?ImmutableObject Immutable objects] from [[Portland Pattern Repository]]
* [https://web.archive.org/web/20150809185757/http://facebook.github.io/immutable-js/ Immutable.js] by Facebook
* [https://persistent.codeplex.com/ Immutable structures in C#] {{Webarchive|url=https://web.archive.org/web/20171221010951/http://persistent.codeplex.com/ |date=2017-12-21 }} opensource project in Codeplex
* [https://msdn.microsoft.com/en-us/library/system.collections.immutable(v=vs.111).aspx Immutable collections in .NET] official library by Microsoft
* [https://www.tutlane.com/tutorial/csharp/csharp-string-with-examples#divcsstimu Immutable objects in C#] by Tutlane.com
Line 470 ⟶ 499:
[[Category:Object (computer science)]]
[[Category:Functional programming]]
[[Category:Articles with example Ada code]]
[[Category:Articles with example C Sharp code]]
[[Category:Articles with example C++ code]]
[[Category:Articles with example D code]]
[[Category:Articles with example Java code]]
[[Category:Articles with example JavaScript code]]
[[Category:Articles with example Perl code]]
[[Category:Articles with example Python (programming language) code]]
[[Category:Articles with example Racket code]]
[[Category:Articles with example Scala code]]
[[Category:Functional data structures]]
|