简体   繁体   中英

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 just 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?

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

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");
  }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM