Emily Tsang
Emily Tsang

Reputation: 115

Generic class for operations on Number

I am writing a Java class to represent a range. I would like to make it more general so that the range can be any Number type, but the two values v1 and v2, must be in the same Number type.

Although I can do comparison on them, I cannot add or subtract the values. I know the operation on two different number types cause problem (e.g. Float + Integer), and so do subclasses of Number, e.g. BigInteger and BigDecimal. But in my case, v1 and v2 should be of the same type.

class Range<T extends Number & Comparable<T>> {
    public T v1;
    public T v2;
    public Range(T v1, T v2) {
        if (v1.compareTo(v2) > 0)
            throw new IllegalArgumentException("Value-1 must be smaller or equal to Value-2.");
        this.v1 = v1;
        this.v2 = v2;
    }
    public T length() {
        return v2 - v1; // Compilation error
    }
}

Recently I only come up with an idea like this:

public T add(T t1, T t2) {
    if (t1 instanceof Integer) {
        // ...
    }
    if (t1 instanceof Long) {
        // ...
    }
} 

But is there any better design to create the Range class? Thanks!

Upvotes: 2

Views: 122

Answers (1)

Chetan Kinger
Chetan Kinger

Reputation: 15212

Make Range and length() abstract. Also note that v1 and v2 should be protected.

abstract class Range<T extends Number & Comparable<T>> {
    protected T v1;
    protected T v2;
    public Range(T v1, T v2) {
        if (v1.compareTo(v2) > 0)
            throw new IllegalArgumentException("Value-1 must be smaller or equal to Value-2.");
        this.v1 = v1;
        this.v2 = v2;
    }

    public abstract T length(); 
}

extend the range class for specific types :

class IntegerRange extends Range<Integer> {
     @Override
      public Integer length() {
          return v2 - v1;
      }
 }

This is in line with the open-closed principle. A class should be open for extension, but closed for modification. Using instanceof checks is the easiest way to go against this principle since Range will need to modified for each new type that it has to support. This should be avoided in your case.

Upvotes: 2

Related Questions