ski*_*iwi 5 java oop interface java-8 default-method
我有几个关于Java 8中"新"接口的问题,我有以下代码:
public interface Drawable {
public void compileProgram();
public Program getProgram();
public boolean isTessellated();
public boolean isInstanced();
public int getInstancesCount();
public int getDataSize();
public FloatBuffer putData(final FloatBuffer dataBuffer);
public int getDataMode();
public boolean isShadowReceiver();
public boolean isShadowCaster(); //TODO use for AABB calculations
default public void drawDepthPass(final int offset, final Program depthNormalProgram, final Program depthTessellationProgram) {
Program depthProgram = (isTessellated()) ? depthTessellationProgram : depthNormalProgram;
if (isInstanced()) {
depthProgram.drawArraysInstanced(getDataMode(), offset, getDataSize(), getInstancesCount());
}
else {
depthProgram.drawArrays(getDataMode(), offset, getDataSize());
}
}
default public void draw(final int offset) {
if (isInstanced()) {
getProgram().use().drawArraysInstanced(getDataMode(), offset, getDataSize(), getInstancesCount());
}
else {
getProgram().use().drawArrays(getDataMode(), offset, getDataSize());
}
}
default public void delete() {
getProgram().delete();
}
public static int countDataSize(final Collection<Drawable> drawables) {
return drawables.stream()
.mapToInt(Drawable::getDataSize)
.sum();
}
public static FloatBuffer putAllData(final List<Drawable> drawables) {
FloatBuffer dataBuffer = BufferUtils.createFloatBuffer(countDataSize(drawables) * 3);
drawables.stream().forEachOrdered(drawable -> drawable.putData(dataBuffer));
return (FloatBuffer)dataBuffer.clear();
}
public static void drawAllDepthPass(final List<Drawable> drawables, final Program depthNormalProgram, final Program depthTessellationProgram) {
int offset = 0;
for (Drawable drawable : drawables) {
if (drawable.isShadowReceiver()) {
drawable.drawDepthPass(offset, depthNormalProgram, depthTessellationProgram);
}
offset += drawable.getDataSize(); //TODO count offset only if not shadow receiver?
}
}
public static void drawAll(final List<Drawable> drawables) {
int offset = 0;
for (Drawable drawable : drawables) {
drawable.draw(offset);
offset += drawable.getDataSize();
}
}
public static void deleteAll(final List<Drawable> drawables) {
drawables.stream().forEach(Drawable::delete);
}
}
Run Code Online (Sandbox Code Playgroud)
(许多人的一个实施)
public class Box implements Drawable {
private FloatBuffer data;
private Program program;
private final float width, height, depth;
public Box(final float width, final float height, final float depth) {
this.width = width;
this.height = height;
this.depth = depth;
data = generateBox();
data.clear();
}
@Override
public void compileProgram() {
program = new Program(
new VertexShader("data/shaders/box.vs.glsl").compile(),
new FragmentShader("data/shaders/box.fs.glsl").compile()
).compile().usingUniforms(
UNIFORM_MODEL_MATRIX,
UNIFORM_VIEW_MATRIX,
UNIFORM_PROJECTION_MATRIX,
UNIFORM_SHADOW_MATRIX
);
}
@Override
public Program getProgram() {
return program;
}
@Override
public boolean isTessellated() {
return false;
}
@Override
public boolean isInstanced() {
return false;
}
@Override
public int getInstancesCount() {
return 0;
}
@Override
public int getDataSize() {
return 6 * 6;
}
@Override
public FloatBuffer putData(final FloatBuffer dataBuffer) {
FloatBuffer returnData = dataBuffer.put(data);
data.clear(); //clear to reset data state
return returnData;
}
@Override
public int getDataMode() {
return GL_TRIANGLES;
}
@Override
public boolean isShadowReceiver() {
return true;
}
@Override
public boolean isShadowCaster() {
return true;
}
private FloatBuffer generateBox() {
FloatBuffer boxData = BufferUtils.createFloatBuffer(6 * 6 * 3);
//putting lots of floats in boxData
return (FloatBuffer)boxData.clear();
}
}
Run Code Online (Sandbox Code Playgroud)
问题:
Drawable不会在伪代码会被实例化和既不能被镶嵌,因此isTessellated() = false,isInstanced() = false,getInstancesCount() = 0,那会是有效的具有这种性质的声明默认的方法?你所做的看起来似乎应该是有效的(我还没有真正使用过 Java 8 的东西,但我知道它),但它并不是真正最好的面向对象设计。
最好将其作为扩展的抽象类来完成(特别是因为 Box 不扩展任何内容,但实现了可绘制对象),因为这样您还可以在类中存储数据并拥有实现它的方法。
现在,这些方法最好位于静态实用程序类中,以实现它们在类内部的所有用途。(我知道他们会调用isTesselated,但静态实用程序类也可以做到这一点)。