我尝试在我的 2D 游戏引擎中实现流畅的界面。
我的实现的简化示例:
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");
我不断收到错误:“函数 setAlive(boolean) 不存在。”
我知道,反过来使用我的方法(以更合乎逻辑的顺序)是有效的:
Entity entity = new Entity().setName("Zombie").setAlive(true).setPosition(100, 200);
而且我知道覆盖每个子类中的任何父 setter 函数都可以:
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);
}
}
但我希望界面对“最终用户”来说尽可能自由/简单,并且代码尽可能<强>紧凑、干净。
我不知道是我搞砸了泛型还是我的漏洞方法完全错误。我希望你能帮忙。我愿意接受任何建议。 (抱歉我的英语不好。)
编辑: 我已经测试了以下方法,它适用于实体类。
public class Sprite<T> {
...
}
public class Living<T> extends Sprite<T> {
...
}
public class Entity extends Living<Entity> {
...
}
我忘了提及,我还需要实例化 Sprite & Living。例如:
Living living = new Living().setPosition(50, 50).setAlive(false);
最佳答案
这是curiously recurring template pattern的一次勇敢尝试在 java 。问题在于您混合了泛型和原始类型,这意味着您没有“关闭模式的循环”。例如您的Living
声明:
public class Living<T extends Living> extends Sprite<Living>
实际上应该是:
public class Living<T extends Living<T>> extends Sprite<T>
在某些时候,您需要声明一个解析 T
的“leaf”类,否则您将无法在不诉诸原始类型或通配符的情况下实例化和声明这些类型的变量(这违背了该模式的目的)。例如:
public final class ConcreteEntity extends Entity<ConcreteEntity>
查看我的回答 here有关实现此模式的更多详细信息。
关于Java(处理1.5.1): Fluent interface @ multilevel inheritance via generics,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13812190/