0

I'm trying to combine method chaining with class extensions and a method that is defined in a base class. However, I struggle to get it to work, as I am not very familiar with Generics yet. Could someone maybe help me to get this to work? It would be really appreciated. Thanks!

Current situation:

public abstract class A<T extends A<?>> extends F // the base class, all others extend this one (either direct or indirect)
public T isLoaded() { // method defined in class A
    // Omitted
    return (T) this;
}

public class B extends A<B> // One of the classes that extends the base class
public D tapButton() // Method defined in class B

public class C extends A<C> // Another class that extends the base class, also has a child itself
public C setAmount(int amount) // method defined in class C

public class D extends C // Class that extends the previous one (C)
public E tapButtonTwo() // Method defined in class D, can't move this one level up to due to other parts of the code

Code that tries to use these classes and methods:

// Failing scenario
protected void doSomething() {
    // I already have an instance of type B, but I omitted this part
    b.tapButton() // returns type D
        .isLoaded() // returns type C and is the cause of the problem
        .setAmount(10) // returns type C
        .tapButtonTwo() // fails on: cannot resolve method
}

// Scenario that does work:
protected void doSomething() {
    // I already have an instance of type B, but I omitted this part
    b.tapButton() // returns type D
        .setAmount(10) // now returns type D
        .tapButtonTwo() // works
}
Alex
  • 223
  • 1
  • 6
  • 21
  • What's a class extension? – nicomp May 02 '19 at 11:47
  • 1
    Notice that `D` extends `C`, which means it extends `A` and *not* `A`. – JimmyB May 02 '19 at 11:50
  • You are `D` class extends `C`, where the `C` class will always return a `C` type object when `isLoaded` is invoked. You can simply override the `isLoaded` method in your `D` class, to return a D type object instead of the downcast to `C`. – Rann Lifshitz May 02 '19 at 11:53
  • @RannLifshitz No, won't work, because `C` would have to declare to return a `D`, which it can't. – JimmyB May 02 '19 at 11:54
  • 2
    Related: [Java Generic Builder](https://stackoverflow.com/questions/39015564/java-generic-builder/39019511#39019511) – MC Emperor May 02 '19 at 11:55
  • How is "class extension" different from inheritance? – nicomp May 02 '19 at 11:56
  • @JimmyB : I explicitly stated - the override should be done in the `D` class, which extends `C`, thus inheriting all of `C`s methods. Overriding `isLoaded` in the `D` class will allow returning the instance as an actual `D` instance instead of a `C` instance. – Rann Lifshitz May 02 '19 at 12:38
  • @RannLifshitz I see what you mean now. Didn't consider that option because it kind-of breaks the contract of `A`. – JimmyB May 02 '19 at 12:46
  • @JimmyB : Correct - indicating there might be an issue with the entire design IMHO. – Rann Lifshitz May 02 '19 at 14:45

0 Answers0