2

I don't know if this is at all possible, but I was thinking of something in Java:

If I have an abstract parent class, I can do this:

public ParentClass add(ParentClass a, ParentClass b);

If ParentClass then has a child and I want to override this method, the child class will still have a ParentClass add(ParentClass, ParentClass) method.

Is there a way to make the parent function derive itself to each child?
I don't know if I'm wording it right, but something like this:

// ParentClass.java
public ParentClass add(ParentClass a, ParentClass b);

// Foo.java
@Override // or an equivalent
public Foo add(Foo a, Foo b) {}

// Bar.java
@Override
public Bar add(Bar a, Bar b) {}

Notice how each child doesn't have a ParentClass add(...) function, but rather one for each of their own types instead?

Obviously I can just make these myself, but I want to be able to create overridable ones in parents. I've never seen this in practice before, so I doubt its existence. I just want to clarify with someone with a higher Java knowledge than me. Thanks.

In theory, which I guess no language has ever done, something like this:

public child add(child a, child b);
// where *child* is the type of the child inheriting the method
davidxxx
  • 104,693
  • 13
  • 159
  • 179

2 Answers2

3

In Java covariance of parameters of a method is not allowed.
This inherited method : public ParentClass add(ParentClass a, ParentClass b); is legal for all children as it will allow to specify any subclass of ParentClass as parameters.
It is more flexible.
Now, if you don't want this flexibility and you want to force a specific type for parameters in the inherited method, you should use a generics abstract class.

public abstract class ParentClass <T extends ParentClass <?>>{
    public abstract ParentClass<?> add(T a, T b);
}

And in child class you could write :

public class ChildClass extends ParentClass <ChildClass>{
    public ParentClass<?> add(ChildClass a, ChildClass b){
       ....
   }
}
davidxxx
  • 104,693
  • 13
  • 159
  • 179
  • Lovely! Just one thing; is there any way I could somewhat automatically set the generic type to the child's class without having to include it? i.e. remove `` completely? –  May 09 '17 at 08:11
  • No you cannot. The Java language doesn't work in this way. You have to specify it explicitly. – davidxxx May 09 '17 at 08:19
  • 1
    You are welcome :) And in a some way it is much better like that otherwise it could force undesirable behavior if you don't want replace the type in the subclass by the child class itself. Besides, specifying a type in the class declaration is "cheap". – davidxxx May 09 '17 at 08:23
  • Oh ofcourse! The reason I'm asking is because I'm developing a grammar for a language and want to create operator overloading. By having every class derive from this parent, I can just set the overloads for them all. I can always just generate the children with `<...>` in the classes though... –  May 09 '17 at 08:25
  • What problem, if any, would there be if something like this had been written instead `public interface Addable { T add (T a, T b); }`? Wouldn't this be preferable, e.g. `public class Child implements Addable { Child add(Child a, Child b) { ... } }`? – code_dredd May 10 '17 at 12:32
  • @ray It would not cause any problem. It is still a design choice. In the question of the user, it could make sense. Now, this way has the ability to force the Child type (or any subclass) use as returned type but this has as consequence to loose the benefit to return any compatible subclass of Addable. Finally you reduce the inheritance principle by limiting it to a specific subset. So you should use it only with this constraint in mind. – davidxxx May 10 '17 at 16:40
  • @davidxxx *"this has as consequence to loose the benefit to return any compatible subclass of Addable"* Not sure I follow that statement. How can you lose the benefit when any 'subclass of `Addable`' is simply any class that *implements* the interface? As long as they're `Addable`, they should be fine. – code_dredd May 12 '17 at 04:16
  • In your example, you cannot any longer declare the method in this way as it was originally: `Addable> add(Child a, Child b)`. But you cannot return another child that doesn't inherit from Child either. For example : `OtherChild add(Child a, Child b)` It expects as returned type Child or subclass of it. That is my point : you are forced to return a Child or a derived from it. – davidxxx May 12 '17 at 07:06
  • Why the wildcard? Why `ParentClass>` instead of `ParentClass`? – user2357112 supports Monica May 29 '17 at 03:26
1

Something like this could work with Generics:

public abstract class ParentClass<T extends ParentClass> {
    public abstract T add(T a, T b);
}

class Foo extends ParentClass<Foo> {
    @Override
    public Foo add(Foo a, Foo b) {
        return null;
    }
}

class Bar extends ParentClass<Bar> {
    @Override
    public Bar add(Bar a, Bar b) {
        return null;
    }
}
Yosef Weiner
  • 4,522
  • 22
  • 35
  • Thankyou! This is exactly what I'm looking for. Never seen generics used like this, but its perfect. –  May 09 '17 at 08:10