Here is a Java program that implements a simple counter.
class Counter
{
private int count;
public Counter() {
this.count = 0;
}
public int getCount() {
return this.count;
}
public boolean isLessThan(int n) {
return this.count < n;
}
public void increment() {
this.count += 1;
}
}
public class Main
{
public static void main(String[] args)
{
Counter counter = new Counter();
while (counter.isLessThan(10))
{
System.out.println(counter.getCount());
counter.increment();
}
}
}
In the following refactored version of the same program, we have instead replaced Counter
with a class called ImmutableCounter
. Note that we added the final
keyword to the count
field to make the class immutable. In Java, a field declared final
cannot be changed after object instantiation.
final class ImmutableCounter
{
private final int count;
public ImmutableCounter(int count) {
this.count = count;
}
public static ImmutableCounter zero() {
return new ImmutableCounter(0);
}
public int getCount() {
return this.count;
}
public boolean isLessThan(int n) {
return this.count < n;
}
/* -------------------------------------------- */
/* 1. Implement method for incrementing counter */
/* -------------------------------------------- */
}
public class Main
{
public static void main(String[] args)
{
ImmutableCounter counter = ImmutableCounter.zero();
while (counter.isLessThan(10)) {
System.out.println(counter.getCount());
/* ------------------------- */
/* 2. Increment counter here */
/* ------------------------- */
}
}
}
We can’t modify the counter object, so how would you write the two missing pieces of code, assuming the rest of the program remains the same? Hint: Immutable data structures favor construction over mutation. Look at the zero
method for a clue.
What are some advantages of programming with immutable data and implicit state? (For instance, why are Java strings immutable?) Are there any disadvantages? I guess that was more than one question :)
public ImmutableCounter next() {
return new ImmutableCounter(this.count + 1);
}
counter = counter.next();
Immutability eliminates side-effects, which makes code easier to reason about and to test. Immutable objects are inherently thread-safe. A disadvantage is that it can be more difficult to write time- and resource-efficient code using immutable data.