开发者

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());
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜