Forget about inheritance. It will force you to handle both CustomBigDecimal
s and non-custom BigDecimal
s.
Imagine what you would do if you wanted to add a convenience toProperCase()
method to the String
class (and this is a very common and frequent issue). You would be forced to create a StringUtils
class, because the String
class is final
. The downside is that then you will need to use StringUtils.toProperCase(someString)
instead of someString.toProperCase()
.
If the String
class was not final
, you could create a subclass and add the method there. But this would sucks, you still could not do someString.toProperCase()
, you would need something like:
if (!(someString instanceof MyStringSubclass)) {
someString = new MyStringSubclass(someString);
}
String somethingElse = ((MyStringSubclass) someString).toProperCase();
And, that code is indeed horrible. In your CustomBigDecimal
class, you hit the same issue:
if (!(someBigDecimal instanceof CustomBigDecimal)) {
someBigDecimal = new CustomBigDecimal(someBigDecimal);
}
CustomBigDecimal somethingElse = ((CustomBigDecimal) someBigDecimal).reciprocal();
And again, that sort of code sucks.
In ruby, javascript and some other languages, you could mixin some new method into an existing class without having to alter it. This would be the correct solution for the problem. Unfortunately, java does not allows this. So, the better solution is the utils approach:
public class BigDecimalUtils {
private BigDecimalUtils() {}
public static BigDecimal reciprocal(BigDecimal a) {
...
}
}
The utils approach is an anti-pattern, but since there is no way to mixin a method into an existing java class, it is the best approach to do. Using a subclass is still a worse anti-pattern. The correct solution would be to add mixins to the java language, but this is of course not an option.
Note: I am not considering options regarding in altering the actual classes in the JDK's rt.jar file, nor to emulate that with bytecode-manipulating classloaders. That would be a serious overkill for this.