Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In most OOP languages, objects are generally mutable with a limited set of exceptions (like e.g. tuples and strings in python). In most functional languages, data is immutable.

Both mutable and immutable objects bring a whole list of advantages and disadvantages of their own.

There are languages that try to marry both concepts like e.g. scala where you have (explicitly declared) mutable and immutable data (please correct me if I am wrong, my knowledge of scala is more than limited).

My question is: Does complete (sic!) immutability -i.e. no object can mutate once it has been created- make any sense in an OOP context?

Are there designs or implementations of such a model?

Basically, are (complete) immutability and OOP opposites or orthogonal?

Motivation: In OOP you normally operate on data, changing (mutating) the underlying information, keeping references between those objects. E.g. an object of class Person with a member father referencing another Person object. If you change the name of the father, this is immediately visible to the child object with no need for update. Being immutable you would need to construct new objects for both father and child. But you would have a lot less kerfuffle with shared objects, multi-threading, GIL, etc.

share|improve this question
2  
Immutability can be simulated in an OOP language, by only exposing object access points as methods or read-only properties that do not mutate the data. Immutability works the same in OOP languages as it does in any functional language, except that you may be missing some functional language features. –  Robert Harvey 8 hours ago
1  
Mutability is not a property of OOP languages like C# and Java, nor is immutability. You specify mutability or immutability by the way you write the class. –  Robert Harvey 8 hours ago
4  
Your presumption seems to be that mutability is a core feature of object-orientation. It isn't. Mutability is simply a property of objects or values. Object-orientation encompasses a number of intrinsic concepts (encapsulation, polymorphism, inheritance, etc.) that have little or nothing to do with mutation, and you would still derive the benefits of those features. even if you made everything immutable. –  Robert Harvey 8 hours ago
1  
@MichaelT The question is not about making specific things mutable, it's about making all things immutable. –  delnan 8 hours ago
2  
show 11 more comments

6 Answers

up vote 10 down vote accepted

OOP and immutability are almost completely orthogonal to each other. However, imperative programming and immutability are not.

OOP can be summarized by two core features:

  • Encapsulation: I will not access the contents of objects directly, but rather communicate via a specific interface (“methods”) with this object. This interface can hide internal data from me. Technically, this specific to modular programming rather than OOP. Accessing data via a defined interface is roughly equivalent to an abstract data type.

  • Dynamic Dispatch: When I call a method on an object, the executed method will be resolved at run time. (E.g. in class-based OOP, I might call a size method on a IList instance, but the call might be resolved to an implementation in a LinkedList class). Dynamic dispatch is one way to allow polymorphic behavior.

Encapsulation makes less sense without mutability (there is no internal state that could be corrupted by external meddling), but it still tends to make abstractions easier even when everything is immutable.

An imperative program consists of statements which are executed sequentially. A statement has side effects like changing the state of the program. With immutability, state cannot be changed (of course, a new state could be created). Therefore, imperative programming is fundamentally incompatible with immutability.

It now happens that OOP has historically always been connected with imperative programming (Simula is based on Algol), and all mainstream OOP languages have imperative roots (C++, Java, C#, … are all rooted in C). This does not imply that OOP itself would be imperative or mutable, this just means that the implementation of OOP by these languages allows mutability.

share|improve this answer
1  
Thank you very much, especially for the definition of the two core features. –  Hyperboreus 7 hours ago
add comment

Immutability can be simulated in an OOP language, by only exposing object access points as methods or read-only properties that do not mutate the data. Immutability works the same in OOP languages as it does in any functional language, except that you may be missing some functional language features.

Your presumption seems to be that mutability is a core feature of object-orientation. But mutability is simply a property of objects or values. Object-orientation encompasses a number of intrinsic concepts (encapsulation, polymorphism, inheritance, etc.) that have little or nothing to do with mutation, and you would still derive the benefits of those features, even if you made everything immutable.

Not all functional languages require immutability, either. Clojure has a specific annotation that allows types to be mutable, and most of the "practical" functional languages have a way to specify mutable types.

A better question to ask might be "Does complete immutability make sense in imperative programming?" I'd say the obvious answer to that question is no. To achieve complete immutability in imperative programming, you would have to forego things like for loops (since you would have to mutate a loop variable) in favor of recursion, and now you're essentially programming in a functional manner anyway.

share|improve this answer
 
Thank you. Could you please elaborate a bit your last paragraph ("obvious" might be a bit subjective). –  Hyperboreus 8 hours ago
 
Already did.... –  Robert Harvey 8 hours ago
 
Thank you again and good answer. I have to digest it a bit. I also think that polymorphism and (not inheritance, but) derivation also figure quite centrally in functional languages. –  Hyperboreus 8 hours ago
 
It's hard to see how the kind of polymorphism that we use in OO has much to do with FP. –  Robert Harvey 7 hours ago
1  
@Hyperboreus There are many ways to achieve polymorphism. Subtyping with dynamic dispatch, static ad-hoc polymorphism (aka. function overloading) and parametric polymorphism (aka generics) are the most common ways to do that, and all ways have their strengths and weaknesses. Modern OOP languages combine all these three ways, whereas Haskell primarily relies on parametric polymorphism and ad-hoc polymorphism. –  amon 7 hours ago
show 1 more comment

Note, there's a culture among object oriented programmers where people assume if you're doing OOP that most of your objects will be mutable, but that's a separate issue from whether OOP requires mutability. Also, that culture seems to be slowly changing toward more immutability, due to people's exposure to functional programming.

Scala is a really good illustration that mutability isn't required for object-orientation. While Scala supports mutability, its use is discouraged. Idiomatic Scala is very much object oriented and also almost entirely immutable. It mostly allows mutability for compatibility with Java, and because in certain circumstances immutable objects are inefficient or convoluted to work with.

Compare a Scala list and a Java list, for example. Scala's immutable list contains all the same object methods as Java's mutable list. More, in fact, because Java uses static functions for operations like sort, and Scala adds functional-style methods like map. All the hallmarks of OOP—encapsulation, inheritance, and polymorphism—are available in a form familiar to object-oriented programmers and used appropriately.

The only difference you'll see is when you change the list you get a new object as a result. That often requires you to use different design patterns than you would with mutable objects, but it doesn't require you to abandon OOP altogether.

share|improve this answer
add comment

In c# some types are immutable like string.

This seems to furthermore suggest that the choice has been strongly considered.

For sure it's really performance demanding to use immutable types if you have to modify that type hundred of thousand of times. That's the reason why it's suggested to use the StringBuilder class instead of the string class in this cases.

I've made an experiment with a profiler and using the immutable type is really more CPU and RAM demanding.

It's also intuitive if you consider that for modifying just one letter in a string of 4000 characters you have to copy every char in another area of the RAM.

share|improve this answer
4  
Frequently modifying immutable data does not need to be catastrophically slow as with repeated string concatenation. For virtually all kinds of data/use cases, an efficient persistent structure can be (often already has been) invented. Most of those have roughly equal performance, even if the constant factors are sometimes worse. –  delnan 8 hours ago
 
@delnan I also think that the last paragraph of the answer is more about an implementational detail than about (im)mutability. –  Hyperboreus 8 hours ago
 
@Hyperboreus: do you think I should delete that part? But how can a string change if it is immutable? I mean.. in my opinion, but for sure I can be wrong, that could be the main reason why object are not immutable. –  Revious 8 hours ago
1  
@Revious By no means. Leave it, so it causes discussion and more interesting opinions and points of view. –  Hyperboreus 7 hours ago
1  
@Revious Yes, reading would be slower, though not as slow as changing a string (the traditional representation). A "string" (in the representation I'm talking about) after 1000 modifies would be just like a freshly created string (modulo contents); no useful or widely used persistent data structure degrades in quality after X operations. Memory fragmentation is not a serious problem (you'd have many allocations, yes, but fragmentation is well a non-issue in modern garbage collectors) –  delnan 6 hours ago
show 2 more comments

I think it depends on whether your definition of OOP is that it uses a message-passing style.

Pure functions don't have to mutate anything because they return values which you can store in new variables.

var brandNewVariable = pureFunction(foo);

With message passing style, you tell an object to store new data instead of asking it what new data you should store in a new variable.

sameOldObject.changeMe(foo);

It's possible to have objects and not mutate them, by making its methods pure functions that happen to live on the inside of the object instead of outside.

var brandNewVariable = nonMutatingObject.askMe(foo);

But it's not possible to mix message passing style and immutable objects.

share|improve this answer
add comment

Complete immutability of everything doesn't make much sense in OOP, or most other paradigms for that matter, for one very big reason:

Every useful program has side effects.

A program that does not cause anything to change, is worthless. You may as well not have even run it, as the effect will be identical.

Even if you think you're not changing anything, and are simply summing up a list of numbers you somehow received, consider that you need to do something with the result -- whether you print it to standard output, write it to a file, or wherever. And that involves mutating a buffer and changing the state of the system.

It can make a lot of sense to restrict mutability to the parts that need to be able to change. But if absolutely nothing needs to change, then you're not doing anything worth doing.

share|improve this answer
 
I fail to see how your answer relates to the question as I didn't address pure functional languages. Take erlang for example: Immutable data, no destructive assignment, no hazzle about side effects. Also you have state in a functional language, only that the state "flows" through the functions, unlike the functions operating on the state. The state changes, but it doesn't mutate in place, but a future state replaces the current state. Immutability is not about whether a memory buffer is changed or not, it is about whether these mutations are visible from the outside. –  Hyperboreus 4 hours ago
 
And a future state replaces the current one how, exactly? In an OO program, that state is a property of an object somewhere. Replacing the state requires changing an object (or replacing it with another, which requires a change to the objects that refer to it (or replacing it with another, which...eh. You get the point)). You might come up with some type of monadic hack, where every action ends up creating a whole new application...but even then, the current state of the program has to be recorded somewhere. –  cHao 3 hours ago
2  
-1. This is incorrect. You're confusing side effects with mutation, and while they're often treated the same by functional languages, they are different. Every useful program has side effects; not every useful program has mutation. –  Michael Shaw 1 hour ago
 
@Michael: When it comes to OOP, mutation and side effects are so intertwined that they can not be realistically separated. If you have no mutation, then you can not have side effects without massive amounts of hackery. –  cHao 1 hour ago
 
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.