我有以下代码,我今天刚刚对此进行了重构,因为我理解<T extends Buffer>
的真正含义,这是简化版本:
public class Buffer {
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;
}
public <T extends Buffer> T create() {
assertNotCreated();
bufferId = GL15.glGenBuffers();
created = true;
return (T)this;
}
public boolean hasBeenCreated() {
return created;
}
private void assertNotCreated() {
if (hasBeenCreated()) {
throw new RuntimeException("Buffer has been created already.");
}
}
}
public class ArrayBuffer extends Buffer {
public ArrayBuffer(final int bufferDataType) {
super(GL15.GL_ARRAY_BUFFER, bufferDataType);
}
}
public class DynamicDrawArrayBuffer extends ArrayBuffer {
public DynamicDrawArrayBuffer() {
super(GL15.GL_DYNAMIC_DRAW);
}
}
警告发生在Buffer.create()
,是否可以安全地取消警告?有没有办法让它更安全?
另一个要求是不应该在此API的调用/使用代码中添加任何混乱,具体地说这意味着DynamicDrawArrayBuffer
可能无法附加泛型。
答案 0 :(得分:4)
这显然不是类型安全的。你可以写
ArrayBuffer a = new ArrayBuffer(0);
DynamicDrawArrayBuffer d = a.create();
这将导致ClassCastException
。从调用站点推断出create
方法的返回类型。此处呼叫网站上唯一可用的信息是返回值必须为DynamicDrawArrayBuffer
- 因此ArrayBuffer
被粗暴地归为一个。
我认为你可以在这里轻松利用协方差:create
方法总能返回类的类型。然后,create
方法的返回类型由调用方法时的类型信息确定:
public class BufferTest
{
public static void main(String[] args)
{
ArrayBuffer a = new ArrayBuffer();
ArrayBuffer aa = a.create(); // Yes
// DynamicDrawArrayBuffer ad = a.create(); // No
DynamicDrawArrayBuffer d = new DynamicDrawArrayBuffer();
ArrayBuffer da = a.create(); // Yes
DynamicDrawArrayBuffer dd = d.create(); // Yes
Buffer b = a;
Buffer bb = b.create(); // Yes
//ArrayBuffer ba = b.create(); // No
}
}
class Buffer
{
public Buffer create()
{
// create etc...
return this;
}
}
class DynamicDrawArrayBuffer extends ArrayBuffer
{
@Override
public DynamicDrawArrayBuffer create()
{
super.create();
return this;
}
}
class ArrayBuffer extends Buffer
{
@Override
public ArrayBuffer create()
{
super.create();
return this;
}
}
答案 1 :(得分:2)
更简化的版本:
public class Buffer {
public <T extends Buffer> T create() {
return (T)this;
}
public static class FooBuffer extends Buffer {}
public static class BarBuffer extends FooBuffer {}
public static void main(String... args) {
BarBuffer b = new FooBuffer().create();
}
}
main
方法在没有警告的情况下编译,在ClassCastException
中运行代码结果。 create
中的警告指出代码中确实缺乏类型安全。