Java: использование обобщений для реализации класса, который работает с различными типами чисел - PullRequest
3 голосов
/ 13 ноября 2008

Итак, допустим, я хочу написать класс, который будет работать с разными типами чисел, но я априори не знаю, над какими числами (т. Е. С целыми числами, двойными и т. Д.) Я буду работать.

Я хотел бы использовать дженерики для создания общего класса для этого сценария. Что-то вроде:

 Adder<Double> adder = new Adder<Double>();
 adder.add(10.0d, 10.0d);   // = 20.0d

Но я не могу создать экземпляр универсального типа, который передаю своему классу Adder! Итак - что делать?

Ответы [ 6 ]

6 голосов
/ 13 ноября 2008

Э-э-э, --- шаблоны не являются шаблонами C ++. Из-за стирания типа Double в вашем примере даже не будет отображаться в системе времени выполнения.

В вашем конкретном случае, если вы просто хотите иметь возможность добавлять различные типы вместе, могу я предложить перегрузку метода? например, double add(double, double), float add(float, fload), BigDecimal add(BigDecimal, BigDecimal) и т. д.

2 голосов
/ 13 ноября 2008

Я думаю вы можете делать, что хотите, но я не уверен, учитывая предоставленную вами информацию. Звучит так, как будто вы хотите что-то из следующего:

public class Foob<T extends Number> {

    public T doSomething(T t1, T t2) {
        return null;
    }
}
0 голосов
/ 11 августа 2009

Если бы вы могли жить с преобразованием всего в двойное число для вычисления, вы могли бы использовать полиморфизм

Number someNumberFunction(Number n1, Number n2) 
{
  double
      d1 = n1.doubleValue(),
      d2 = n2.doubleValue();

  /* perform computations on d1 & d2 */
}

К сожалению, это не будет хорошо работать на BigInteger или BigDecimal

0 голосов
/ 13 ноября 2008

Я согласен с Лапли. Перегрузка - это то, что вам поможет. Самое близкое, что вы можете получить, используя дженерики, примерно так:

открытый класс NumericOps
{
public T add (T n1, T n2) {
//n1.add(n2);
// Это невозможно, потому что у Number нет метода add, следовательно
// вам нужно будет определить тип n1.
// Мы не можем определить тип U, потому что он не будет существовать во время выполнения
// из-за стирания типа
if (n1 instanceof Integer) {
// добавляем целые числа ...
}
else if (n1 instanceof Double) {
// добавляем двойки
}
вернуть ноль;
}
}

Но это не очень помогает, потому что нет пользы от использования дженериков.

0 голосов
/ 13 ноября 2008

Я не уверен, что здесь вам нужны дженерики. Обобщения в java предназначены для обеспечения ограничений времени компиляции , а не полиморфизма во время выполнения. Я думаю, что вы действительно хотите использовать перегрузку. Используя дженерики, вы получите что-то вроде:

interface Adder<T> {
   T add(T arg1, arg3);
}

и куча:

class DoubleAdder implements Adder<Double> {
   Double add(Double arg1, Double arg2) {
      return arg1.add(arg2);
   }
}

а затем куча:

if (arg1 instanceof Double) {
   Adder<Double> adder = new DoubleAdder();
}

Использование генериков ничего не спасет.

0 голосов
/ 13 ноября 2008

Если вы не знаете, с какими числами вы будете работать, то, вероятно, вы не будете использовать собственные переменные экземпляра. В этом случае вы можете написать статические методы и вам никогда не нужно создавать экземпляр вашего класса.

Если вам действительно нужны ваши собственные промежуточные переменные, то вам, вероятно, придется определять их по-разному для каждого класса пользовательских переменных, с которыми вы работаете. Например, если кто-то пытается использовать ваш класс для работы с переменными BigDecimal , вы, вероятно, не будете использовать переменные int для промежуточных результатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...