Blog
All Blog Posts | Next Post | Previous PostObject Pascal: Immutable State
Tuesday, April 17, 2018
In object-orientation, an object can be considerable immutable even if it... changes.
IntroductionLearning a complex concept tends to be better absorbed if we divide the concept into small parts.
For example, when we begin to learn English, we are taught that to refer to something that happened in the past, we must use past verbs to make affirmations or use the modal verb did or did not to ask questions or denials. This is the verbal tense Past Simple.
Example: "I saw this movie".
Then, as you begin to study the language more, you discover that there are many other ways of expressing something that has occurred in the past. For example, the use of verb tense Present Perfect.
Example: "I have seen this movie".
Here we see the use of the modal verb to have and the use of Past Participle of the verb to see.
Both sentences say the same when we translate to Portuguese, for example, but the second sentence can be considered more correct than the first one you only discover this after you learn the Present Perfect. But this is not an English article, so let's go back to object-orientation.
This introduction is to show you that we must first learn a concept in its simplest form; then we improved.
Concepts of ImmutabilityWhen you've learned about immutability you may have thought that an object is immutable if, after it is created, nothing is changed inside it or that the object always returns the same information when a method is called.
Well, that is not so simple.
Unlike functional languages, where everything is immutable by default, in object-orientation this concept may be broader.
Let's take a look in some concepts.
External contentA class that represents a file could be immutable in two ways:
type TFile = class private FFilePath: string; FStream: IDataStream; public constructor Create(const FilePath: string); function Stream: IDataStream; end; implementation constructor TFile.Create(const FilePath: string); begin FFilePath := FilePath; end; function TFile.Stream: IDataStream; begin if not Assigned(FStream) then FStream := TDataStream.New(FFileName); Result := FStream; end;
In the code above, the TFile.Stream: IDataStream
method will always return the same value read on the first run.
The object is immutable and constant.
But, what if we change the method like below, the class will continue been immutable?
function TFile.Stream: IDataStream; begin Result := TDataStream.New(FFileName); end;
Yes, for sure.
Although the result of the method may be different for each call the contents of the file can be changed by another process the object would remain unchanged because its state (FFilePath
attribute) has not been changed.
It is immutable, but not constant.
The same concept applies to content coming from a Database, Website, etc.
Content in MemoryCan a list of objects be considered immutable if we add items after it is created?
Let's take a look in this code:
type TDataParams = class(TInterfacedObject, IDataParams) private FList: TInterfaceList; public constructor Create; class function New: IDataParams; overload; destructor Destroy; override; function Add(Param: IDataParam): IDataParams; overload; // ... end; implementation { TDataParams } constructor TDataParams.Create; begin inherited Create; FList := TInterfaceList.Create; end; class function TDataParams.New: IDataParams; begin Result := Create; end; destructor TDataParams.Destroy; begin FList.Free; inherited; end; function TDataParams.Add(Param: IDataParam): IDataParams; begin Result := Self; FList.Add(Param); end;
The TDataParams
class encapsulates a list of TInterfaceList
.
At each inclusion of a new item, the in-memory persistence of the objects is delegated to this internal list.
Do you think we're changing the object state (FList
)?
We are not.
The reason is that we are not redefining FList
. We are not creating a new list.
A list of items is being created in memory memory blocks but the initial address of FList
remains intact.
Also, FList
is a secondary attribute, so we could even redefine this attribute without being in disagreement with the principle. But, if the list instance were passed in the constructor, then we could not redefine the object because it would be considered as a primary attribute.
If even after some internal or external changes to the object, it is still considered immutable, how do we know if we are not violating the principle of immutability?
Simple: If the state of the object, ie., its primary attributes, is not changed/redefined, then it is immutable.
Once an attribute is instantiated, it can not have its memory address changed. These attributes will be initialized in the constructor of the class and can never be reinitialized.
Your object must be faithful to arguments passed in the class constructor, however it is free to work and respond to whatever you want in your methods.
ConclusionImmutability, in object-orientation, is not about internal or external changes to the object, but about not changing the primary state of it.
Do not confuse data with object state.
So, we need to work with these concepts in mind.
See you.
Marcos Douglas B. Santos
This blog post has received 4 comments.
Steven
If you can change the contents of a publicly acccessible list, it is indeed mutable (not immutable). If the list is purely private, and only internal state is modified, then the object is not necessarily mutable.
Rudy Velthuis
You''ve got the idea.
And you''re right, that was a typo. Thanks.
Marcos Douglas B. Santos
All Blog Posts | Next Post | Previous Post
"Can a list of objects be considered mutable if we add items after it is created? "
No, it can''t. You then go on to try to prove that it can by creating an object that hides a list from the outside. Unfortunately, you do not explain what this object is intended to do nor show its complete code, meaning we cannot determine whether it is immutable or not. If its behavior depends on what''s in that list, then it is NOT immutable.
In fact, think of a parallel operation. What about two threads attempting to add objects to that list at the same time? If you have to worry about locking, you''re not dealing with an immutable object. What about hashing? If hashing depends on what''s in that list, it''s also not an immutable object.
You also go on about memory addresses, which have nothing to do with being immutable or not.
I feel this article only serves to muddy the waters regarding what immutability, which should be a simply subject.
Joseph