#Chain calling methods of parent, child and child's child object

1 messages · Page 1 of 1 (latest)

wintry jolt
#

Currently i got an generic abstract parent class and a child class like this:

public abstract class Parent<C, T extends Parent>
{
  protected abstract T getThis();

  ... other methods like this:
  public T doSomething1()
  {
    ...
    return getThis();
  }
}

public class Child<B> extends Parent<B, Child<B>>
{
  @Override
  protected Child<B> getThis() { return this; }

  ... other methods like this:
  public Child<B> doSomething2()
  {
    ...
    return getThis();
  }
}```

This allows me to basically chain the doSomething methods.
Now i want to implement another child of child:

```public class Grandchild<A> extends Child<A>
{
  @Override
  protected Grandchild<A> getThis() { return this; }

  ... other methods like this:
  public Grandchild<A> doSomething3()
  {
    ...
    return getThis();
  }
}```

The first problem now is that i cannot chain anymore because the original child still returns the Child<B>. So in this case i think i would need to generic type the child class too:
```public class Child<B, T extends Child<B, T>> extends Parent<B, Child<B, T>>```
But if i do this, i would need to change the getThis method in Child to this:
```protected T getThis() { return this; }```
But this doesnt work because returning requires T, but i return Child<B, T>

My other problem with this is, that i cannot initialize a new instance of Child, because i obviously need a Child<B, T> and i dont get a T by directly instantiating Child.

What do i do wrong or how could i fix this?
smoky prairieBOT
#

<@&987246399047479336> please have a look, thanks.

wintry jolt
#

I'm also open for other ideas.

shut vapor
#

Ah yes, CRTP as a replacement for self types

#

If your inheritance is more than 1 class deeper, you need to employ abstract classes

#

In your case, that would be AbstractChild and AbstractGrandchild. Those classes are part of the inheritance, and they implement all the methods you need.
Then, you make Child extend AbstractChild and Grandchild extend AbstractGrandchild.
Their only purpose is to pin down the generics and method return types, they all simply call the super method (or maybe you don't even need to redefine the methods, I don't remember rn) .

#

In the end, what you get is a tree, where the "trunk" is made out of abstract classes, and each new layer is a "leaf"

#

If you're familiar with Lombok, you can try delomboking it's @SuperBuilder annotation, this is exactly how it operates under the hood.

wintry jolt
#

Oh, that is genius. Thanks, gonna try it and come back later on!