views:

77

answers:

3

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?

A: 

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());
    }
}
BigMac66
Sure. With two child classes child1 and child2, both extending Parent<Child1> and Parent<Child2> respectively, I'd like to be able to create a child1 object and call child1.set(child2 object).
I am inclined to agree with user183406, though I only had to change the GrandParent class set method. See my test classes above. Not sure if this creates other unwanted problems later though as I had lots of quirky things happen while I was playing around...
BigMac66
A: 

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.

meriton
A: 

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

}
erickson