I want to do some calculations with money. In order to prevent rounding errors I decided to use BigDecimal instead of double or float. Now I think, this wasn't a good idea, because it makes calculations extremly difficult.
I created a class named Euro that extends from BigDecimal in order to override the toString and equals methods.
Now, if I want to add a number to an Euro object, I would do it like
Euro sum = (new Euro(10)).add(new Euro(15));
The problem here is that add(...) returns an object from class BigDecimal which I can not cast to Euro, so I added this to the Euro class:
public Euro add(Euro euro){
return new Euro(euro.add((BigDecimal) this).floatValue());
}
What can I do now, instead of rewriting all methods from BigDecimal in Euro? I guess, the best solution is to use an integer for cents instead of BigDecimal, because than I can write
int sumCents = 1000 + 1500;
instead of the long term above.
It would be better to favor composition over inheritance in this case. When you're subclassing BigDecimal
to make Euro
, you are saying that a Euro
is a BigDecimal
. It would be more accurate to say that an amount of Money
has a BigDecimal
(or in general, an amount). It also has a symbol, here a Euro.
You could also use a different implementation, e.g. number of cents as you already have thought of, to store the amount as an integer. This is a clue that inheriting from BigDecimal
isn't correct. Also, it doesn't make sense to call pow
on a Euro
, even though it makes sense on a BigDecimal
. A Euro
is not a BigDecimal
.
Besides, calling floatValue
(or doubleValue
) just to convert to Euro
would have defeated the point of using BigDecimal
in the first place - to avoid floating-point round-off errors when representing an amount of money.
When you use composition, then you can expose only the methods you want, e.g. add
and subtract
, without overriding methods and creating new subclass objects during each mathematical operation. The mathematical operations are done on an instance variable, not on the class as a whole, as an implementation detail.