user3822430
user3822430

Reputation: 3

Generic Averaging - need a Generic Type but have an int instead

I'm trying to implement an abstract generic average class. It must have a concrete method for averaging. How does one get around the problem of division, dividing the number of elements (which is always an integer) by the sum of the array or array list? I'm using an array here. Using an array list has the same issue. It appears I must supply the array size but I really should not have to.

EDIT: The generic average class shall have three only methods where E is a generic type: E add(E f, E s); E divide(E f, E s); and E setToZero(). There shall be one concrete class with a signature of E average(E[] array). The numbers must be represented as objects of a class, like Integer and Double, not primitives int and double. I think that changes the tenor of the question. Thanks for the help so far. I appreciate this forum. END_EDIT

With the above in mind, this code below compiles but is not what is required. I believe I've done my due diligence without success looking here.

EDIT2: My customer (Java instructor) said he was fine with int as the second argument and had no problem with adding another method to the class. I do not think the problem was defined well in that is was over constrained and not intended to be.

public abstract class GenericAverage<E>
{
    private E sum;
    private E average;

    public GenericAverage()
    {
        sum     = setToZero();
        average = setToZero();
    }

    public E Average(E[] array, E size) // wrong, it must be "E Average(E[] array)"
    {
        //E thisSize = 0; // which of course won't work
        for (int i = 0; i < array.length; i++) // to get that array length as an E      {
            sum = add(sum, array[i]);
            //thisSize = thisSize + 1; //which will not work
        }
        average = divide(sum, size);
        //average = divide(sum, getSize(array));  // maybe this is the answer I seek?  
        return average;
    }

    public abstract E add(E f, E s);
    public abstract E divide(E f, E s);
    public abstract E setToZero();
    //public abstract E getSize(E[] f);  // maybe this is the way to the answer?
}

Upvotes: 0

Views: 1727

Answers (2)

meskobalazs
meskobalazs

Reputation: 16031

Well, this works for Integer, Long, Float and Double.

public abstract class AbstractAverage<E> {

    private E sum;
    private E average;

    public AbstractAverage() {
        sum = setToZero();
        average = setToZero();
    }

    public E average(E[] array) {
        for (int i = 0; i < array.length; i++) {
            sum = add(sum, array[i]);
        }
        average = divide(sum, array.length);
        return average;
    }

    public abstract E add(E f, E s);
    public abstract E divide(E f, int s);
    public abstract E setToZero();
}

If you absolutely want the second parameter of divide to be of type E, then store the class type of the generic E in the constructor and cast your variable to it. That is however ugly, and achieves nothing, really.

However this divide method may be reasonable, as was suggested in the comments.

public abstract E divide(E f, Number s);

Upvotes: 3

tom
tom

Reputation: 22979

There's been a suggestion to use array.length and change the signature of divide to take an int for the second argument.

If it is important for divide to take arguments of type E, consider adding a method

public abstract E fromInt(int f);

and using that to convert the length to E.

That method could also replace setToZero(), or at least be used in a default implementation.


In the interest of code reuse, consider moving add(), divide(), etc. to a separate class, Calculator<E>. An instance of Calculator would then be given to GenericAverage on creation.

You may even want to move average() to the Calculator class.

Upvotes: 0

Related Questions