我正在研究以下结构:
Buffer
XBuffer
扩展Buffer
XYBuffer
扩展XBuffer
所有对象都应该是可实例化的,所以没有abstract
,以支持向前兼容性。
我想出了以下内容,我将在下面描述陷阱/问题:
public class Buffer<S extends Buffer<S>> {
protected final int bufferType;
protected final int bufferDataType;
protected int bufferId;
protected boolean created;
public Buffer(final int bufferType, final int bufferDataType) {
this.bufferType = bufferType;
this.bufferDataType = bufferDataType;
}
@SuppressWarnings("unchecked")
public S create() {
assertNotCreated();
bufferId = GL15.glGenBuffers();
created = true;
return (S)this;
}
@SuppressWarnings("unchecked")
public S bind() {
assertCreated();
GL15.glBindBuffer(bufferType, bufferId);
return (S)this;
}
@SuppressWarnings("unchecked")
public S fillData(final float[] data) {
assertCreated();
FloatBuffer dataBuffer = BufferUtils.createFloatBuffer(data.length).put(data);
dataBuffer.flip();
GL15.glBufferData(bufferType, dataBuffer, bufferDataType);
return (S)this;
}
public void delete() {
assertCreated();
GL15.glDeleteBuffers(bufferId);
}
public int getBufferId() {
return bufferId;
}
public boolean hasBeenCreated() {
return created;
}
private void assertCreated() {
if (!hasBeenCreated()) {
throw new RuntimeException("Buffer has not been created.");
}
}
private void assertNotCreated() {
if (hasBeenCreated()) {
throw new RuntimeException("Buffer has been created already.");
}
}
@Override
public String toString() {
return "Buffer(" + bufferType + ", " + bufferDataType + ", " + bufferId + ", " + created + ")";
}
}
public class ArrayBuffer<S extends ArrayBuffer<S>> extends Buffer<S> {
public ArrayBuffer(final int bufferDataType) {
super(GL15.GL_ARRAY_BUFFER, bufferDataType);
}
}
public class StaticDrawArrayBuffer extends ArrayBuffer<StaticDrawArrayBuffer> {
public StaticDrawArrayBuffer() {
super(GL15.GL_STATIC_DRAW);
}
}
现在发生以下情况:
StaticDrawArrayBuffer
按预期工作。ArrayBuffer
无法按预期工作,因为我不能在不使用泛型的情况下实例化它。 (请记住:此处使用的泛型仅用于帮助我,而不是实际提供通用功能)Buffer
无法正常工作,问题与ArrayBuffer
相同。我想要什么?
Buffer
和ArrayBuffer
。我该怎么做?
为了澄清更多,这些陈述应该全部编译:
Buffer buffer = new Buffer().create().bind();
ArrayBuffer arrayBuffer = new ArrayBuffer().create.bind();
StaticDrawArrayBuffer staticDrawArrayBuffer = new StaticDrawArrayBuffer().create.bind()
如果我根本不使用任何泛型,那么new ArayBuffer().create()
将返回Buffer
,导致无法将其分配给ArrayBuffer
。它确实保留了Buffer
方法的链接,但如果链包含仅ArrayBuffer
可用的方法,它还会中断。
如果它有帮助,我有能力使用Java 8,如果它几乎是无bug的(现在应该是现在,我想?),考虑到这个项目无论如何都不会看到真正的日光。
答案 0 :(得分:1)
Covariant返回类型而不是泛型呢?
public class ArrayBuffer extends Buffer {
public ArrayBuffer(final int bufferDataType) {
super(GL15.GL_ARRAY_BUFFER, bufferDataType);
}
public ArrayBuffer create() {
super.create();
return this;
}
public ArrayBuffer bind() {
super.bind();
return this;
}
}
public class StaticDrawArrayBuffer extends ArrayBuffer {
public StaticDrawArrayBuffer() {
super(GL15.GL_STATIC_DRAW);
}
public StaticDrawArrayBuffer bind() {
super.bind();
return this;
}
}
AFAIK现在应该编译:
Buffer buffer = new Buffer().create().bind();
ArrayBuffer arrayBuffer = new ArrayBuffer().create().bind();
StaticDrawArrayBuffer staticDrawArrayBuffer = new StaticDrawArrayBuffer().create().bind()
答案 1 :(得分:0)
一种可能性是将不使用泛型的代码部分与通用继承树分开(在我看来,这是一种笨拙的开头,但这主要是Java设计方式的问题,将泛型添加到语言中时所做的设计选择。)
我的意思是执行以下操作:
public class Buffer extends BaseBuffer<Buffer> {
public Buffer(final int bufferType, final int bufferDataType) {
super(bufferType, bufferDataType);
}
}
public class ArrayBuffer extends BaseArrayBuffer<ArrayBuffer> {
public ArrayBuffer(final int bufferDataType) {
super(bufferDataType);
}
}
BaseBuffer
和BaseArrayBuffer
是您拨打Buffer
和ArrayBuffer
的课程。
(虽然看起来你可能已经根据你的一条评论做了这个吗?)
此方法的问题在于,您无法将StaticDrawArrayBuffer
作为ArrayBuffer
或ArrayBuffer
作为Buffer
传递(或将其存储在这些类型的变量中)因为它们不再是那些特定类型的子类。您必须使用类似BaseArrayBuffer<StaticDrawArrayBuffer>
和BaseBuffer<ArrayBuffer>
的内容。
答案 2 :(得分:0)
我强烈建议您重新考虑您的架构。实例化子项和父类是一个坏主意。假设,有一天你想改变父行为(因为你使用它并且要求已经改变),同时让孩子完好无损。那么呢?
改用策略。指定缓冲区接口(为什么需要它?它应该做什么?)并为每个实例提供一个策略来实现它们的目的。
然后你将只有包含Buffers和Strategies的Buffer来实现你的逻辑:
public interface BufferingStrategy
{
public Buffer create() ;
public Buffer bind();
public Buffer fillData(final float[] data);
}