Access static field of generic type

Khuldraeseth na'Barya :

Can I require classes implementing an interface to have a certain static field or method and access/invoke that field or method through a generic type argument?

I have an interface, Arithmetical<T>, which specifies several functions like T plus(T o) and T times(T o). I have as well a Vector<N extends Arithmetical<N>> class, which is intended for vectors (of variable dimension) with components of type N. I ran into an issue, however, when trying to implement the dot product.

I want to implement the method N dot(Vector<N> o). For this, I plan to start with whatever N's zero is and iterate through both Vector<N>s' List<N>s, adding the product of each pair of elements to my total. Is there a way to specify in Arithmetical<T> that all implementing classes must have a static (and preferably final) field ZERO and start dot(Vector<N> o)'s body with something along the lines of N sum = N.ZERO;?

If not, what other approaches might there be to this problem? I want to allow 0-dimensional vectors, so I can't just begin by multiplying the vectors' first components. Is there a way to instantiate an object of a generic type, so I can merely specify a T zero() method in Arithmetical<T>?

I have a reason for not using Java's numerical types—I want to have vectors with complex components.

Here's Arithmetical:

public interface Arithmetical<T> {
    public T plus(T o);
    public T minus(T o);
    public T negate();
    public T times(T o);
    public T over(T o);
    public T inverse();
    // Can I put a line here that requires class Complex (below) to define ZERO?
}

Vector:

public class Vector<N extends Arithmetical<N>> {

    private List<N> components;
    public Vector<N>(List<N> cs) {
        this.components = new ArrayList<N>(cs);
    }

    public N dot(Vector<N> o) {
        // Here's where I need help.
    }

}

And Complex:

public class Complex implements Arithmetical<Complex> {

    public static final Complex ZERO = new Complex(0, 0); // Can I access this value through N if <N extends Arithmetical<N>>?

    private double real;
    private double imag;
    public Complex(double r, double i) {
        this.real = r;
        this.imag = i;
    }

    /* Implementation of Arithmetical<Complex> (and some more stuff) not shown... */

}

I'm quite new to Java (and programming in general); I will likely not understand complex (ha) explanations and workarounds.

Thanks!

(Python is a suggested tag... Huh.)

rgettman :

You need a "zero" for every possible implementation type. A constant in the interface won't do, because a constant cannot be overridden and must remain the same.

The solution is to add a new method to your Arithmetical interface:

public T zero();

Each implementation is forced to implement this and return its own version of zero. In this case, you're using it as a starting point for adding; it's the additive identity.

The Complex class implementation would look like this.

@Override
public Complex zero() {
    return ZERO;
}

If your instances are mutable, then don't use a constant; just return new Complex(0, 0).

Another idea is to borrow from what Streams do when reduce-ing items and combining them to one single item -- take an identity value that represents the initial state, i.e. no items collected yet -- zero.

public N dot(Vector<N> o, N identity) {
    N dotProduct = identity;
    // Perform operations on each item in your collection
    // to accumulate and return a dot product.
}

The caller will have to supply the identity value.

Complex dotProduct = vectorOfComplex.dotProduct(otherVector, new Complex(0, 0));

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=464853&siteId=1