How to do a template class (where the template extends Number) which use number addition?

Hello I want to do a really simple thing. Just make a template function for any numbers. I actually want as little as ability to "add". In C++ it would be really trivial like this:

template <typename T> inline T add (T a, T b) { return a + b; } int main(int argc, char** argv){ printf("int: %d\n",add(1,2)); printf("float: %f\n",add(1.1,2.1)); }

In Java I got a tough lesson. I'm new to Java so I believe (and hope) I'm totally wrong and over engineering this. But only thing I come up with was:

public interface IntrfcWowNumbersAdds<T> { T add(Number v); } public class SuperSmartInteger extends Number implements IntrfcWowNumbersAdds<SuperSmartInteger>{ private Integer i; public SuperSmartInteger(int v) { i = v; } @Override public String toString(){ return ""+i; } @Override public SuperSmartInteger add(Number v) { return new SuperSmartInteger(this.intValue()+v.intValue()); } @Override public int intValue() { return i; // thx god for auto(un)boxing } @Override public long longValue() { return i; } @Override public float floatValue() { return i; } @Override public double doubleValue() { return i; } }

And note that this crazy wrapper above I would have to do for any number I would like to use template for (eg double, byte etc...)

public class ThreadSafeNum<T extends Number & IntrfcWowNumbersAdds<T>> { private T num; public ThreadSafeNum(T n){ num = n; } public T add(T v){ // note in here I plan to do some locking... return num = num.add(v); } }

then I can use it as:

SuperSmartInteger i = new SuperSmartInteger(5); SuperSmartInteger i2 = i.add(6); System.out.println(""+i2); ThreadSafeNum<SuperSmartInteger> tsn = new ThreadSafeNum<SuperSmartInteger>(i); SuperSmartInteger i3 = tsn.add(i2);

I know that when add() would be only adding I can just use + operator and rely on auto(un)boxing. But my add() method is meant to do something extra (like lock).

So how to do it properly? Or is my way correct???

-------------Problems Reply------------

Something like this as the base class:

public abstract class Addable<T extends Number,U extends Addable<T,U>> {
private final T value;
public Addable( final T value ){ this.value = value; }
public T getValue(){ return value; }
public abstract U add( U addend );
}

And this as the sub-class:

public class AddableInteger extends Addable<Integer,AddableInteger> {
public AddableInteger( final Integer value ){
super( value );
}

@Override
public AddableInteger add( final AddableInteger addend ){
java.util.Objects.requireNonNull( addend );
return new AddableInteger( this.getValue() + addend.getValue() );
}
}

Well, the reasons that works in C++ is that the compiler will create as many functions as there are calls in the code, and compile each one independently in order to validate if '+' is a reasonable thing to do in that particular case. This is a little like a case of compiler-assisted duck-typing. In other words, there is no guarantee that type T will have a + operator and only the fact that the compiler will look at the actual call types and create permutations helps you.

Note that there is some risk in letting the compiler "add whatever", since there is no interface or contract that guarantees the semantics to be correct. That is what a class hierarchy brings you.

This is trickier to do in full type safety since inheritance can be complex and the return types need to be somewhat clear. Inheritance is the usual thing so that a virtual method knows how to add its own type, but in this case you can't change the class hierarchy of Number.

You can, nevertheless, do something like this:

public static int addAsInt(Number a, Number b)
{
a.intValue() + b.intValue();
}

And the same for other return types. That will take any two instances of number and generate an output value, assuming which kind of output type you want. Somewhat easier than creating wrapper classes in this particular case.

Category:java Views:0 Time:2018-05-11

Related post

Copyright (C) dskims.com, All Rights Reserved.

processed in 0.347 (s). 11 q(s)