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 operationsabstract 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 needclass 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 factoryclass 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.