Common approaches are:
- Make a protective copy (e.g. return a copy of
Wheel ) - Make
Wheel immutable (anytime you want to change it, instead you create a new one, created with a new color) - Do not return the
Wheel , return an immutable interface on the Wheel , which returns only getters, mutation operations - As Sandeep said , make the setter more limited than the receiver, say package-private for the setter and
public for the receiver. Then the classes inside the package can set the Wheel color, but the classes outside the package cannot. (I prefer # 3 in this situation for a clear separation, but this also works if you cross the line of sight.)
This third option is one of the reasons why instance variables (fields) not private are often considered bad practice.
Here is # 3 in more detail, simply because it is more complex than # 1 and # 2, and not because it is necessarily better (itโs not so, the choice of design is made in context).
A read-only interface, usually open or batch-private, depending on how you intend to use all of this:
public interface Wheel { int getColor(); }
A specific class, usually private-private (may be a private static nested class inside Truck , if this is the only place he used):
class WheelImplementation implements Wheel { private int color; WheelImplementation(int color) { this.color = color; } public int getColor() { return this.color; } void setColor(int color) { this.color = color; } }
Truck , usually the same visibility as Wheel :
public class Truck { private WheelImplementation wheel; Truck(){ this.wheel = new WheelImplementation(); } Wheel getWheel() { return this.wheel; } }
Of course, this can be played through reflection, but in general, you are developing an API for use, not abuse. :-)
source share