Search code examples
javagenericsprocessingfluent-interfacemethod-chaining

Java (Processing 1.5.1): Fluent interface @ multilevel inheritance via generics


I try to implement a fluent interface in my 2D game engine.

Simplified example of my implementation:

public class Sprite<T> {

    protected float x = 0.0;
    protected float y = 0.0;

    public T setPosition(float x, float y) {
        this.x = x;
        this.y = y;
        return (T)this;
    }

}

public class Living<T extends Living> extends Sprite<Living> {

    protected boolean alive = false;

    public T setAlive(boolean alive) {
        this.alive = alive;
        return (T)this;
    }

}

public class Entity<T extends Entity> extends Living<Entity> {

    protected String name = null;

    public T setName(String name) {
        this.name = name;
        return (T)this;
    }

}


Entity entity = new Entity().setPosition(100, 200).setAlive(true).setName("Zombie");

I keep getting the error: "The function setAlive(boolean) does not exist."

I know, using my methods the other way round (in a more logical order) works:

Entity entity = new Entity().setName("Zombie").setAlive(true).setPosition(100, 200);

And I know that overwriting any parent setter functions in each and every child class would work:

public class Entity extends Living {

    protected String name = null;

    public Entity setPosition(float x, float y) {
        return (Entity)super.setPosition(x, y);
    }

    public Entity setAlive(boolean alive) {
        return (Entity)super.setAlive(alive);
    }

    public Entity setName(String name) {
        return (Entity)super.setName(name);
    }

}

But I want the interface to be as free/uncomplicated as possible for the 'end user' and the code to be as compact and clean as it gets.

I don't know if I just messed up the generics or my hole approach is completely wrong. I hope you can help. I am open to any advice. (Sorry for my bad english.)

Edit: I already tested the following approach and it works for the Entity class.

public class Sprite<T> {
...
}

public class Living<T> extends Sprite<T> {
...
}

public class Entity extends Living<Entity> {
...
}

I forgot to mention, that I need to instantiate Sprite & Living too. For example:

Living living = new Living().setPosition(50, 50).setAlive(false);

Solution

  • I think your class model is over complicated, you can pass generic parameter down to the child class and then declare it explicitly:

    public class Sprite<T> {
    ...
    }
    
    public class Living<T> extends Sprite<T> {
    ...
    }
    
    public class Entity extends Living<Entity> {
    ...
    }