Sunday, 23 June 2013

KCandy Brand Decides To Be Unchanged with time...THE IMMUTABLE CLASS

Hello friends,

Lets have a class CandyInfo.java with the following properties :

private String brandName;
private float price;

and following methods,

public String getBrandName() {
return brandName;
}
public void setBrandName(String brandName) {
this.brandName = brandName;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}

Now lets have a class KCandyBrand.java with the following properties:

private String         ownerInitials  = "K";
private CandyInfo  candyInfo ;

,with the constructor as:

public KCandyBrand (CandyInfo candyInfo) {
this.candyInfo = candyInfo;
}

and the methods as 

public CandyInfo getCandyInfo() {
return candyInfo;
}

public void setOwnerInitials(String ownerInitials) {
this.ownerInitials = ownerInitials;
}

public String getOwnerInitials() {
return ownerInitials;
}

Only getter method for property : candyInfo  and setter and getter methods for property : ownerInitials .

Lets make the KCandyBrand immutable.

_________________________________________________________________

Time for some terminology:

Immutable : It is an adjective,  meaning : 
Unchanging over time or unable to be changed: "an immutable fact".

** as given by Google : 
_________________________________________________________________

Question 1 : What makes the KCandyBrand MUTABLE?

Answer

Point  1. It can be sub-classed and its behavior can be changed as the subclass of KCandyBrand will also be  KCandyBrand hence KCandyBrand can not be classified as an immutable class.

Approach First :

So lets MARK IT FINAL so that no other class can override the behavior of KCandyBrand.

Approach Second :

Hey what if We make all  constructor of KCandyBrand as private and do not mark the class KCandyBrand as final?

Nice Idea, No class will be successful in extending the KCandyBrand if all constructors of KCandyBrand are private. 

 Hey hey hey, but then how will ever the object of KCandyBrand will come into existence in the world ?

Well then lets have a public method inside the KCandyBrand which will create the object of KCandyBrand and give it to the out side world. Hmm..Lets mark it static. 

Why static ?

Static because for accessing the non static method, an object of the class is required and as we have marked all constructors as private so outside world can not access any constructor so marking the method as static. This static method inside KCandyBrand shall create and return the object of KCandyBrand.

public static KCandyBrand getKCandyBrandObject (CandyInfo candyInfo){
return new KCandyBrand (candyInfo);
}

(Word 'Factory' is associated with these types of static methods because they act as a factory producing the objects of a class!!)

So to summarize approach second : 
1. All constructors marked private.
2. Factory method (static method written inside the KCandyBrand.java returning the objects of KCandyBrand): to obtain the object of the class.

So The catch is : 

If we see String.java then we find its an Immutable class and still have a public constructor
( of course we can call constructor and do  new String("HaKuNaMaTaTa");
But String.java is marked as final :---> Approach One.
So depending upon the situation and implementation requirements any of the above approaches can be implemented to make a class such that no other class can become its subclass.

Point 2:  Now There are setter methods which can reset the properties of KCandyBrand object. 
Lets assume we take approach one mentioned in point 1. and we have marked the class KCandyBrand as final.

Oh Yes! going back we see we have a method 

public void setOwnerInitials(String ownerInitials) {
this.ownerInitials = ownerInitials;
}

which can change the property : String ownerInitials even after creation of the object of KCandyBrand. 

REMOVE THE SETTER METHOD!!

removed...

So Now Our KCandyBrand class is 

1. Marked as final (applying the approach 1 in point 1)
2. No Setter methods, only getter methods to
String ownerInitials;
CandyInfo  candyInfo ;

As

public CandyInfo getCandyInfo() {
return candyInfo;
}

public String getOwnerInitials() {
return ownerInitials;
}

and a public constructor.

public KCandyBrand (CandyInfo candyInfo) {
this.candyInfo = candyInfo;
}

Point 3: There is presence of a mutable property which can be accessed: candyInfo, present inside the class KCandyBrand which can be accessed and the fields of  candyInfo can be modified and hence again the objects of KCandyBrand cannot be said to be Immutable.

Hey how can it be done, aren't we aware of the fact  that we do not have any setter method.

Yeah, we know that but still what if object of KCandyBrand has been created 

CandyInfo candyInfo = new CandyInfo();
candyInfo.setBrandName("KCandy");
candyInfo.setPrice(20);
KCandyBrand kCandyBrandObject = new KCandyBrand(candyInfo);

AND THEN THIS HAPPENS!!

kCandyBrandObject .getCandyInfo().setBrandName("huhaha!!");

Oh No!!

( candyInfo is a property of KCandyBrand and if any of the properties of KCandyBrand is modified then it means the object of KCandyBrand itself has been modified )

We want this object to be immutable and here the brand name has been messed up with, its not immutable yet!!....

RETURN THE COPY OF MUTABLE PROPERTY 

That idea results in the modification of the way getCandyInfo() have been defined.

So now the method looks like: 

public CandyInfo getCandyInfo() {
CandyInfo candyInfoCopy = new CandyInfo();
candyInfoCopy.setBrandName(candyInfo.getBrandName());
candyInfoCopy.setPrice(candyInfo.getPrice());
return candyInfoCopy;
}

So now if
kCandyBrandObject .getCandyInfo().setBrandName("huhaha!!");

ever happens , then this shall not modify the property candyInfo of  kCandyBrandObject as now its the copy of the property candyInfo which gets modified, leaving the object of KCandyBrand untouched and unmodified.

Yuppie!! Now we have the class KCandyBrand as an immutable class.


SUMMARY :


To avoid the class from getting sub-classed and the behavior to be modified either use any of the below approaches :

Approach 1: 

MARK IT FINAL

OR 

Approach 2:

1. Mark all constructors as private.
2. Have a Factory method (public static method written inside the class and returning the objects of the class): to obtain the object of the class.

** some times both Approach 1 and Approach 2 can be used together


To prevent the properties from getting modified by the setter methods.

REMOVE THE SETTER METHOD!!

To avoid the mutable objects, which are  properties  of the class we wish to make immutable, from getting modified 

RETURN THE COPY OF MUTABLE PROPERTIES 

Along with this sometimes all the properties of the class we wish to make immutable can be marked as final so that even from inside the class none of its fields can be re assigned to another object or value depending upon if the property is an Object or primitive type but then this again depends upon the implementation and requirements.



Well sometimes we can have a both the concepts going together in a class. There might be a situation where we may want a part of our class to remain immutable and some part may be flexible so that it can be modified from out side world. We can design our class such that the properties we wish not to be changed remain immutable (encapsulating such part of the class in an immutable class and then having an instance of it in our class without providing setter methods to the instance , marking it private final etc..)***

Shall be back with more stuff...


Good Luck.. 

We are what our thoughts have made us, so take care about what you think. Words are secondary. Thoughts live, they travel far.

Swami Vivekananda.