Sign in to follow this  
scarypajamas

Whats wrong with this java code?

Recommended Posts

I'm just trying to write a simple vector class. The problem is, I keep getting an error:
public class Vec<T extends Number>
{
    public T x, y, z;

    public void add(Vec<T> vec)
    {
        this.x += vec.x;   // ERROR: "Operator + cannot be applied to T, T
        this.y += vec.y;   // ERROR: "Operator + cannot be applied to T, T
        this.z += vec.z;   // ERROR: "Operator + cannot be applied to T, T
    }
}


All I want do do is something like this.
Vec<Double> vd = new Vec<Double>();
Vec<Float> vf = new Vec<Float>();
Vec<Integer> vi = new Vec<Integer>();


Share this post


Link to post
Share on other sites
Number (and indeed, any other Java class) doesn't provide any mechanism to overload operator+ or provide that as a constraint to generics.

Share this post


Link to post
Share on other sites
Number exists. I guess it doesn't do what I thought it did, which was to overload the + operator.

Ok, my question remains, how can I ADD the two generics. Its seems like something this simple should have a simple solution.

Share this post


Link to post
Share on other sites
Quote:
Original post by scarypajamas
My question remains: How can I overload the + operator? I was under the impression that java didn't directly support operator overloading.


You can't, because it doesn't support it indirectly, either. Any "overloads" you see like java.lang.String + whatever are built right into the language.

Share this post


Link to post
Share on other sites
Java doesn't support this. What happens in normal code is auto unboxing and boxing, which allows objects to appear to be using some form of operator overloading (except Strings, they have special handling).

I would just go with using floats for all my vectors. The fact that Java forces one to use reference types to represent vectors at all is a big enough inconvenience, let alone using reference types for each component.

Share this post


Link to post
Share on other sites
Ok, so I can't overload the + operator. But is there a way to still ADD 2 generics with each other or will I have to write 3 separate vector classes for integer, double, and float.


EDIT:
I just read rip-offs post. I will go with all floats instead.

Still, something like this would be trivial in C++.

Share this post


Link to post
Share on other sites
Quote:
Original post by scarypajamas
Ok, so I can't overload the + operator. But is there a way to still ADD 2 generics with each other or will I have to write 3 separate vector classes for integer, double, and float.

No, no, no, you're overcomplicating things, you're stuck in that ancient C++ mindset using that low level approach to code.

What we need here is strategy pattern. Let's define the interface:
interface BinaryMathematicalOperationStrategy {
Number execute();
};

// support for operations
abstract class AbstractBinaryOperationStrategy implements BinaryMathematicalOperationStrategy {
// This is IOC, so we make constructors as lightweight as possible
// no validation is performed here
public AdditionOfTwoDoublesStrategy(Number left, Number right) {
this.leftHandSide = left;
this.rightHandSide = right;
}
public Number getLeftHandSide() {
return leftHandSide;
}
public Number getRightHandSide() {
return rightHandSide;
}
private Number leftHandSide;
private Number rightHandSide;
}

// implement for the operations you need
class AdditionOfTwoDoublesStrategy extends AbstractBinaryOperationStrategy {
public Number execute() {
if (getLeftHandSide() == null || !(getLeftHandSide() instanceof Double)
throw new IllegalArgumentException("Left hand side is not a valid double: " + getLeftHandSide());
if (getRightHandSide() == null || !(getRightHandSide() instanceof Double)
throw new IllegalArgumentException("Right hand side is not a valid double: " + getRightHandSide());
return leftHandSide.doubleValue() * rightHandSide.doubleValue();
}
}

// the above isn't good enough, since don't have an automatic way to get the strategies
// this is trivially solved with a factory
class BinaryMathematicalOperationStratefyFactorySingleton {
private static final class BinaryMathematicalOperationStratefyFactorySingleton instance =
new BinaryMathematicalOperationStratefyFactorySingleton();
BinaryMathematicalOperationStrategy make(Number leftHandSide, Number rightHandSide, String operation) {
String key = leftHandSide.class.getName() + rightHandSide.class.getName() + operation;
Class c = (Class)mappingFromOperationAndTypeToStrategy.get(key);
return key.newInstance(); // pass the parameters here into constructor
}
private BinaryMathematicalOperationStratefyFactorySingleton() {

mappingFromOperationAndTypeToStrategy.put(
// these guys should be loaded from XML
Double.class.toString()+Double.class.toString()+"plus",
AdditionOfTwoDoublesStrategy.class);
// add other operations and type pairs here

}
private final Map<String, Class> mappingFromOperationAndTypeToStrategy =
new HashMap<String, Class>;
};



And that's it, trivial. Now just add this to your vector class and you're good to go:

public void add(Vec<T> vec)
{
BinaryMathematicalOperationStratefy sx =
BinaryMathematicalOperationStratefyFactorySingleton.make(this.x, vec.x);
BinaryMathematicalOperationStratefy sy =
BinaryMathematicalOperationStratefyFactorySingleton.make(this.y, vec.y);
BinaryMathematicalOperationStratefy sz =
BinaryMathematicalOperationStratefyFactorySingleton.make(this.z, vec.z);
this.x = sx.execute();
this.y = sy.execute();
this.z = sz.execute();
}




Quote:
Still, something like this would be trivial in C++.

Everyone knows that operators are evil. You never know what you're going to get, and people abuse them and stuff.

Look at how robust and extensible the Java version is. And it's so easy. Just get a Strategy from a Strategy factory singleton, then pass it the two Numbers and execute it.


PS: The above is what actual enterprise-grade java application designs look like. What would be one line in other languages, is 15 classes, 7 interfaces, and bunch of XMLs. And I didn't even go far enough, the operations should probably be loaded from XMLs, where schema would define the layout to support extensibility to unary and ternary operators, and operations should probably be beans.

Share this post


Link to post
Share on other sites
Off-topic, but...

Quote:
Original post by Antheus
PS: The above is what actual enterprise-grade java application designs look like. What would be one line in other languages, is 15 classes, 7 interfaces, and bunch of XMLs. And I didn't even go far enough, the operations should probably be loaded from XMLs, where schema would define the layout to support extensibility to unary and ternary operators, and operations should probably be beans.


That's my workplace, live. While our 2 Java Enterprise guys are still working on 1 web app, I've finished 5 in PHP. God, do these guys hate me. I wonder if it's because PHP is an "amateur language" or that I'm developing on Windows, not Gentoo like them. Or that I objected their choice of using Gentoo for production systems. [rolleyes]

</rant>

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
Everyone knows that operators are evil. You never know what you're going to get, and people abuse them and stuff.

I like your humor :)

Share this post


Link to post
Share on other sites
You could probably get away with making those variables private. For Java an object can access the private members of another object if they share the same type.

Then again if you're just going to be using "plain" getters+setters you might as well keep them puplic(Getters+setters that do nothing but return or set are bad OO design, so having the core variables of the class public is probably better than that).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this