2013-06-03 3 views
3

Я пытаюсь создать общий класс на Java. Чтение некоторых руководств, я нашел, как объявить его, а также как вызвать его функцию.Generic class - operator issue

Мой класс является точкой и без методов было бы таким образом:

class Pnt<type>{ 
    protected type x, y; 
    protected int col; 
} 

Теперь я пытаюсь сделать add метод, но я не в состоянии сделать это.

То, что я попытался это:

void add(type x_, type y_){ 
    x += x_; 
    y += y_; 
    } 

Инструментальная на меня орать, что += не определено для type переменных ...

Я знаю, что в Java не представляется возможным определить новый оператор как на C++, поэтому я прошу альтернативный способ добавить две переменные type!

P.S. Весь тип, который я буду использовать, будет double s, float s и int egers, вот почему я пытаюсь сделать простую зависимость.

ответ

1

Есть две проблемы: во-первых, если это должно быть быстро, вы должны использовать примитивы напрямую, и они не поддерживаются в качестве параметра в дженериках. Это эффективно означает, что вы должны поддерживать три версии для Point отдельно.

Если вы хотите использовать дженерики, то вы можете использовать соответствующий класс (как Integer), но есть еще одна проблема: их супер тип Number не имеет add метод (не говоря уже оператор + или +=).

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

abstract class Numeric<T extends Number> { 
    public abstract T getValue(); 

    public abstract Numeric<T> add(Numeric<T> other); 

    @Override 
    public String toString() { 
     return getValue().toString(); 
    } 
} 

class MyInt extends Numeric<Integer> { 
    public final Integer value; 

    public MyInt(Integer _value) { 
     super(); 
     this.value = _value; 
    } 

    @Override 
    public Integer getValue() { 
     return this.value; 
    } 

    @Override 
    public Numeric<Integer> add(Numeric<Integer> other) { 
     return new MyInt(this.value + other.getValue()); 
    } 
} 

class MyDouble extends Numeric<Double> { 
    public final double value; 

    public MyDouble(Double _value) { 
     super(); 
     this.value = _value; 
    } 

    @Override 
    public Double getValue() { 
     return this.value; 
    } 

    @Override 
    public Numeric<Double> add(Numeric<Double> other) { 
     return new MyDouble(this.value + other.getValue()); 
    } 
} 

На основании этого можно реализовать, по крайней мере общую точку:

class NumericPoint<T extends Number> { 
    public final Numeric<T> x; 
    public final Numeric<T> y; 

    public NumericPoint(Numeric<T> _x, Numeric<T> _y) { 
     super(); 
     this.x = _x; 
     this.y = _y; 
    } 

    public NumericPoint<T> add(NumericPoint<T> other) { 
     return new NumericPoint<T>(this.x.add(other.x), this.y.add(other.y)); 
    } 

    @Override 
    public String toString() { 
     return "(" + this.x + "/" + this.y + ")"; 
    } 
} 

для использования с

NumericPoint<Integer> ip1 = 
    new NumericPoint<Integer>(new MyInt(1), new MyInt(2)); 
NumericPoint<Integer> ip2 = 
    new NumericPoint<Integer>(new MyInt(3), new MyInt(4)); 
NumericPoint<Integer> ip = ip1.add(ip2); 
System.out.println(ip); 

NumericPoint<Double> dp1 = 
    new NumericPoint<Double>(new MyDouble(1.1), new MyDouble(2.1)); 
NumericPoint<Double> dp2 = 
    new NumericPoint<Double>(new MyDouble(3.1), new MyDouble(4.1)); 
NumericPoint<Double> dp = dp1.add(dp2); 
System.out.println(dp); 

Я изменил ваш пример le: Числа и точки неизменяемые. Он реализован, например, как BigDecimal.Таким образом, метод add относится к родовому классу и возвращает новый экземпляр.

+0

Тяжелый, очень тяжелый, я думаю, у меня будет три разных класса ... К сожалению, это не соответствует моим потребностям, но эй! Вы сделали это возможным! = D – ingroxd

+0

Согласен, это тяжело. Это 'C++ templates', которые решают эту проблему (шаблоны C++ позволяют' int' как параметр шаблона). – Beryllium

+0

Yup, но обработка не поддерживает C++! – ingroxd

3

Когда вы говорите class Pnt<type>, ти означает, что type является объектом, а не примитивный тип данных, как int или double. Вы можете выполнить операцию += на числовых примитивных типах данных, таких как int, float и т. Д., А не на объект. Фактически вы не можете выполнить операцию += с любым общим объектом.

Объектов Integer, Float и т.д. поддержка оператора +=, потому что они являются классами-оболочки и получить распакованные к примитивным типам и autoboxed позже. Но компилятор не может подтвердить, что type будет Integer или Float. Следовательно, он генерирует ошибку времени компиляции.

+0

он не работает с типами объектов. На самом деле утверждение не выполняется при x + = x_; что странно. Думаю, это не имеет ничего общего с примитивами. – ankurtr

+0

Вот почему я должен использовать 'Double' вместо' double' и т. Д. ... Но объекты 'Double',' Float' и 'Integer' поддерживают' + = 'либо! – ingroxd

+0

Да, 'Integer' поддерживает' + = 'оператор, но компилятор не может подтвердить, будет ли' type' '' Integer'. Это может быть «Файл» или любой другой класс. –