The problem
In my own code I sometimes bypass a getter for a final
field in favor of direct field access for struct
-like classes:
public class BigFoot { public final int shoeSize; public BigFoot(final int shoeSize) { this.shoeSize = shoeSize; } }
I figure: why not? As the field is final
there is no need for modifying behavior in a getter method. This seems ideal for data transfer objects (DTOs).
However Miles Barr points out the big flaw with this idea. It is subtle and has to with how the Java compiler deals with direct field access. Miles explains the problem as well as anyone and has a clear example. Fundamentally, you lose polymorphism for shadowed variables and bad things result.
The solution
The mistake for my DTO was not carrying the notion of simple struct
-ness to its full conclusion. How much sense does it make to extend DTOs?
public final class BigFoot { public final int shoeSize; public BigFoot(final int shoeSize) { this.shoeSize = shoeSize; } }
If the class is marked final
then there will never be a problem with shadowing fields in subclasses.
A caveat
Sometimes I want to extend my DTOs when I have a set of similar data to represent and extract out the common fields in to a base class.
But this is an implementation detail. Logically there is no class relationship among the DTOs and the problem with shadowed fields is one which exposes an implementation detail to the user.
So don't do that.
No comments:
Post a Comment