I\'m trying to learn about mutable/immutable classes and I came across this post
Part of the answer provided was:
If you want to enforce immu
If you want to enforce immutability, you cannot have subclasses.
This is almost true, but not entirely. To restate it:
If you want to enforce immutability, you must ensure that all sub-classes are immutable.
The problem with allowing subclassing is that normally anyone who can author a class can subclass any public non-final class.
But all subclasses must invoke one of their super-class's constructors. Package-private constructors can only be invoked by subclasses in the same package.
If you seal packages so that you control which classes are in your package, you can constrain subclassing. First define a class you want to subclass:
public abstract class ImmutableBaseClass {
ImmutableBaseClass(...) {
...
}
}
Since all sub-classes have to have access to the super-constructor, you can ensure all the sub-classes in the package you define follow immutable discipline.
public final class ImmutableConcreteClass extends ImmutableBaseClass {
public ImmutableConcreteClass(...) {
super(...);
}
}
To apply this to your example,
public abstract class Employee {
private final Id id;
private final Name name;
// Package private constructor in sub-classable class.
Employee(Id id, Name name, ...) {
// Defensively copy as necessary.
}
}
public final class Accountant extends Employee {
// Public constructos allowed in final sub-classes.
public Accountant(Id id, Name name, ...) {
super(id, name, ...); // Call to super works from same package.
}
}
public final class ITWorker extends Employee {
// Ditto.
public ITWorker(Id id, Name name, ...) {
super(id, name, ...);
}
}