Абстрактный класс со значением по умолчанию

Я пытаюсь определить абстрактный класс Range, который будет служить базовой реализацией ряда классов диапазонов. Предполагаемое использование не имеет значения для этого вопроса, но до сих пор я:

/**
 * Abstract generic utility class for handling ranges
 */
public abstract class Range<T extends Number> {

  // Variables to hold the range configuration
  private T start;
  private T stop;
  private T step;

  /**
   * Constructs a range by defining it limits and step size.
   *
   * @param start The beginning of the range.
   * @param stop The end of the range.
   * @param step The stepping
   */
  public Range(T start, T stop, T step) {
    this.start = start;
    this.stop = stop;
    this.step = step;
  }
}

Теперь я хочу добавить конструктор с тем, который принимает только start и stop, и устанавливает значение шага по умолчанию 1, независимо от того, какая реализация Number T (например, если T Integer [one] будет иметь значение 1, а если T есть Long [one], будет иметь значение 1L и т.д.). Мне хотелось бы что-то вроде:

protected Range(T start, T stop) {
  this(start, stop, [one]);
}

но я не могу понять, как это установить значение [one]. Поскольку Java по-прежнему для меня совершенно новичок, я пробовал:

private static final T one = 1;

который не работает, потому что T, очевидно, определен в инстанцировании Range.this. Также я пробовал:

protected static abstract T getOne();

который также не работает, потому что T определяется в экземпляре Range.this plus static и abstract не работает вместе.

Мне нужно каким-то образом расширить классы, чтобы они были вынуждены определять значение [one] независимо от того, какая реализация Number Range реализована для.

В конечном итоге я также хотел бы установить нулевое значение как начало по умолчанию, так что я получаю конструктор, который выглядит так:

protected Range(T stop) {
  this([zero], stop, [one]);
}

Ответы

Ответ 1

Одним из решений было бы запросить подклассы для шага по умолчанию:

public abstract class Range<T extends Number> {

    private T start;
    private T stop;
    private T step;

    public Range(T start, T stop, T step) {
        this.start = start;
        this.stop = stop;
        this.step = step;
    }

    protected Range(T start, T stop) {
        this.start = start;
        this.stop = stop;
        this.step = getDefaultStep();
    }

    protected abstract T getDefaultStep();

}

public class IntegerRange extends Range<Integer> {

    public IntegerRange(Integer start, Integer stop, Integer step) {
        super(start, stop, step);
    }

    public IntegerRange(Integer start, Integer stop) {
        super(start, stop);
    }

    @Override
    protected Integer getDefaultStep() {
        return 1;
    }

}

public class DoubleRange extends Range<Double> {

    public DoubleRange(Double start, Double stop, Double step) {
        super(start, stop, step);
    }

    public DoubleRange(Double start, Double stop) {
        super(start, stop);
    }

    @Override
    protected Double getDefaultStep() {
        return 1d;
    }

}

Ответ 2

Вы можете использовать эту реализацию:

protected Range(T start, T stop) {
  this(start, stop, (T) (new Integer(1)));
}

Ответ 3

У вас возникнут другие проблемы... но вот ваш номер 1:

Number ONE = new Number() {
    @Override
    public int intValue() {
        return 1;
    }

    @Override
    public long longValue() {
        return 1L;
    }

    @Override
    public float floatValue() {
        return 1.0f;
    }

    @Override
    public double doubleValue() {
        return 1.0;
    }

    @Override
    public byte byteValue() {
        return 1;
    }

    @Override
    public short shortValue() {
        return 1;
    }
};