Issues with method overriding and generics in Java
I've been fighting with trying to override a method in a generic abstract class.
public abstract class Grandparent<T extends Grandparent>
public T set(final T other) //does stuff I don't want to do
public abstract class Parent<T extends Parent<T>> extends Grandparent<T>
public T set(final Parent<?> other) // does stuff I want to do
All the child classes extend Parent<child>
.
However, I can't call the set() function I want by jus开发者_Go百科t constructing one of the child classes.
Child_1 test = new Child_1();
Child_1 test_2 = new Child_1();
test.set(test_2) //this calls the function I don't want
Parent<Child_1> test_3 = new Child_1();
Parent<Child_1> test_4 = new Child_1();
test3.set(test_4) //this calls the function I do want
This requires modification of already-existing code, however. A lot of it. I don't want to rewrite the set method to
public T set(T other)
because then I'll lose the ability to set one child class object from a different child class object.
How can I write the set() method to trigger any time a child object calls it, passing in any other child object, without any modifications to outside code?
To override a method, you need provide an override-equivalent signature, which implies that the method name and number and types of arguments must be equal. This is not the case For Grandparent.set()
and Parent.set()
. Consequently, Parent.set()
overloads, rather than overrides, Grandparent.set()
.
The simplest solution I see is to generalize the method signatures as follows:
public abstract class Grandparent<T extends Grandparent>
public T set(Grandparent<?> other)
public abstract class Parent<T extends Parent<T>> extends Grandparent<T>
public T set(Grandparent<?> other)
That way, the methods override, and you don't have to modify any child classes.
Subsequent comments helped to clarify what you are after, but I may still be baffled. Perhaps this will help; if not, please try to elaborate on your question.
public abstract class Grandparent<T extends Grandparent<T, Q>, Q extends Grandparent<T, Q>>
{
public abstract Q set(Q other);
}
class Parent<T extends Parent<T>>
extends Grandparent<T, Parent<T>>
{
@Override
public Parent<T> set(Parent<T> other)
{
throw new UnsupportedOperationException("set");
}
}
How can I write the set() method to trigger any time a child object calls it, passing in any other child object, without any modifications to outside code?
Can you include code modeling what you want to do - I just want to be clear what it is you want because at the moment I suspect it simply is not allowed - no matter what you do.
EDIT
Classes I used to test with...
package test.stack.overflow;
public abstract class GrandParent<T extends GrandParent>
{
public T set(final GrandParent<?> other)
{
System.out.println("GrandParent.set=" + other);
return null;
}
}
public abstract class Parent<T extends Parent<T>> extends GrandParent<T>
{
public Parent<?> set(final Parent<?> other)
{
System.out.println("Parent.set=" + other);
return other;
}
}
public class Child_1 extends Parent<Child_1>
{
}
public class Child_2 extends Parent<Child_2>
{
}
public class TestPeerage
{
public static void main(String[] args)
{
Child_1 c1 = new Child_1();
c1.set(new Child_2());
c1.set(new Child_1());
Parent<Child_1> pc1 = new Child_1();
pc1.set(new Child_2());
pc1.set(new Child_1());
}
}
精彩评论