Reputation: 3
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
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
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