So I read discussion about Numbers here, because I have a similar Problem.
In my case, I wanna be able to allow mathematical operations on Numbers. My idea was to write an immutable ´RealNumber´ class that handles primitive Numbers (Integer, Long, Float and Double), without a bunch of instanceof controls. Someone mentioned to Overload Methods and let the compiler do the work.
This was my first attempt:
simple TestClass:
public class Test {
public static void main(String[] args) {
RealNumber<Double> d = RealNumber.create(3.4);
d.add(4.7);
}
}
RealNumber class: (please mention the Method with the comment)
public class RealNumber<N extends Number> extends Number{
N number;
private RealNumber(N number){
if (number == null){
throw new NullPointerException("number is null");
}
this.number = number;
}
public N get(){
return number;
}
//note this Method
public RealNumber<N> add(N number){
return add(number);
}
private RealNumber<Integer> add(Integer number){
return new RealNumber<Integer>(intValue() + number);
}
private RealNumber<Long> add(Long number){
return new RealNumber<Long>(longValue() + number);
}
private RealNumber<Float> add(Float number){
return new RealNumber<Float>(floatValue() + number);
}
private RealNumber<Double> add(Double number){
return new RealNumber<Double>(doubleValue() + number);
}
@Override
public int intValue() {
return number.intValue();
}
@Override
public long longValue() {
return number.longValue();
}
@Override
public float floatValue() {
return number.floatValue();
}
@Override
public double doubleValue() {
return number.doubleValue();
}
public static final RealNumber<Integer> create(Integer number){
return new RealNumber<Integer>(number);
}
public static final RealNumber<Long> create(Long number){
return new RealNumber<Long>(number);
}
public static final RealNumber<Float> create(Float number){
return new RealNumber<Float>(number);
}
public static final RealNumber<Double> create(Double number){
return new RealNumber<Double>(number);
}
}
so the first test leads me to a StackOverflowError, because the method ´add´ always calls itself.
second try (only changed methods)
public RealNumber<N> add(Number number){
return add(number);
}
first wasn't as good, cause it will allow to add BigDecimals, or other things like Boolean, and second leads me to the same StackOverflowError. so I changed:
public RealNumber<N> add(N number){
return add(number);
}
//note the public here
public RealNumber<Double> add(Double number){
return new RealNumber<Double>(doubleValue() + number);
}
//... public RealNumber<Integer, Long, Float> add....
which fails to compile in my TestClass -> "The Method add(Double) is ambiguous for the Type RealNumber
finally this worked:
public RealNumber<N> add(Number number){
return add(number);
}
//note the public here
public RealNumber<Double> add(Double number){
return new RealNumber<Double>(doubleValue() + number);
}
//... public RealNumber<Integer, Long, Float> add....
but brings another 2 issues: this pattern allows to add Doubles to Ints (which results in RealNumber of Integer ), and results in a StackOverflowError if one passes a BigInteger, Byte or some other Number
.
So my main questions:
Why the compiler chooses the right method in Test.class if every add
Method is public and fails, if they are private.
What can I do to fix the issues?