1

I want to make a two-dimensional vector that is holding two numeric values. As usual vectors (even of different numerical type) should e.g. be addable. In C++ you can just do something like:

template<typename T>
class vector2d{

    T x{0};
    T y{0};

public:
    template<typename U> vector2d& operator+=(const vector2d<U>& vec){
        x += vec.x;
        y += vec.y;
        return *this;
    }
    ...

template<typename U>
friend class vector2d;
};

But when I try to achieve this in Java I am coming across some problems. Here is what I tried to do:

class vector2d<T extends Number>{

    private T x;
    private T y;

    public <U extends Number> vector2d add(vector2d<U> vec){
        x += vec.x;
        y += vec.y;
        return this;
    }
    ... 
}

But this does not work. It would if i would use Integer or Float or whatever directly (because of Autoboxing). But this seems not to be the case when you just use the Number class directly. As I think there is no other interface that would satisfy the requirements, I am kind of stuck here. So my question is if there are ways to make this work in Java.

mr.green
  • 92
  • 8
  • What's wrong with your example? What do you expect to happen and what is happening instead? – byxor Aug 19 '16 at 13:42
  • "But this does not work" - is no sufficient description of the Problem you are facing. Do you have compiler errors? – Fildor Aug 19 '16 at 13:43
  • `x += vec.x;` won't work since `x` is private – ArcticLord Aug 19 '16 at 13:43
  • 1
    This is not possible because the compiler will not accept this as there is no "+=" operation for numbers. It only works because of autoboxing for Integer, Float and so on (as I said). – mr.green Aug 19 '16 at 13:45
  • @ArcticLord Yeah that could be. I'll make it public because that is not the problem here. – mr.green Aug 19 '16 at 13:46
  • 2
    No, @ArcticLord is wrong, this has nothing to do with `x` being `private`. You cannot use `+=` on `Number` objects in Java. Note that Java generics do not work in the same way as C++ templates. – Jesper Aug 19 '16 at 13:52
  • Java does not support this because the actions are not well defined for Java type system. Suppose we have `vector2d intVec` and `vector2d doubleVec` with `doubleVec.x = Double.MAX_VALUE`. What would you expect the value of `intVec.add(doubleVec).x` to be? What if `doubleVec.x = Double.NaN`? – bradimus Aug 19 '16 at 13:53
  • @Jesper Unfortunately you are right. But honestly I'm surprised every time I am using them how restricted they really are compared to C++ templates, as you can see at this really basic example. – mr.green Aug 19 '16 at 14:12

1 Answers1

2

One of possibilities to achieve this, is use BigDecimal class:

class vector2d{

    private BigDecimal x;
    private BigDecimal y;

    public void add(vector2d vec){
        x = x.add(vec.x);
        y = y.add(vec.y);
    }
    ...
}

But it can reduce performance of your code, as its operations aren't very fast. You can also keep Number class and use doubleValue always:

class vector2d{

    private Number x;
    private Number y;

    ...

    public void add(vector2d vec){
        x = x.doubleValue() + vec.x.doubleValue();
        y = y.doubleValue() + vec.y.doubleValue();
    }

}

this will allow use any types of numbers:

    vector2d v1 = new vector2d(1, 2.3);
    vector2d v2 = new vector2d(1.3, 2);
    v1.add(v2);

UPD: As @Jesper has mentioned, instead of Number just double type can be used, which will eliminate need of .doubleValue() invocation. So you have various way to do it.

Andremoniy
  • 34,031
  • 20
  • 135
  • 241
  • Why not make `x` and `y` of type `double`? Then you wouldn't have unnecessary boxing and unboxing. – Jesper Aug 19 '16 at 13:54
  • @Jesper, exactly, but just in case if `Number` type is needed for some reasons :) – Andremoniy Aug 19 '16 at 13:56
  • Yeah but this is not really satisfying as e.g. if you want to add two "Integral Vectors" you may do this without losing precision. And just imagine using user-defined Number types. – mr.green Aug 19 '16 at 14:01