多重继承在Java8中的使用
我是在使用Java8的功能还是误用了它 请参考下面的代码和解释,了解为什么选择这样多重继承在Java8中的使用,java,oop,inheritance,multiple-inheritance,java-8,Java,Oop,Inheritance,Multiple Inheritance,Java 8,我是在使用Java8的功能还是误用了它 请参考下面的代码和解释,了解为什么选择这样 public interface Drawable { public void compileProgram(); public Program getProgram(); default public boolean isTessellated() { return false; } default public boolean isInstance
public interface Drawable {
public void compileProgram();
public Program getProgram();
default public boolean isTessellated() {
return false;
}
default public boolean isInstanced() {
return false;
}
default public int getInstancesCount() {
return 0;
}
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.use().drawArraysInstanced(getDataMode(), offset, getDataSize(), getInstancesCount());
}
else {
depthProgram.use().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);
}
}
public类框实现了镶嵌可绘制、InstancedDrawable{
//
静止的{
英国政府工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的工作人员的纹理,工作人员的工作人员的工作人员的纹理,工作人员的工作人员的工作人员的工作人员的纹理,混合颜色,混合颜色,混合颜色,颜色,混合颜色,颜色,德国军队军队的混合颜色,军队军队的颜色,军队的军队军队军队的军队的颜色,男男男男男色,数组,数组,数组,数组,数组,数组,数组,数组,数组,数组,数组,数组,数组,数组,缓冲,数组,缓冲,数组,数组,数组,数组,缓冲,数组,数组,数组,数组,数组U计划| GL_活动|原子|计数器| GL_活动|资源| GL_缓冲|不可变|存储;
int KEEP_OWN_IMPORTS=UNIFORM_PROJECTION_MATRIX.getLocation()| VS_POSITION.getLocation();
}
//
私有缓冲区数据;
私人项目;
专用最终浮子宽度、高度、深度;
公用框(最终浮动宽度、最终浮动高度、最终浮动深度){
这个。宽度=宽度;
高度=高度;
这个。深度=深度;
数据=generateBox();
data.clear();
}
@凌驾
公共无效编译器程序(){
程序=新程序(
新的VertexShader(“数据/着色器/box.vs.glsl”).compile(),
新的FragmentShader(“data/shaders/box.fs.glsl”).compile()
).compile().usingUniforms(
一致_模型_矩阵,
统一视图矩阵,
均匀投影矩阵,
均匀阴影矩阵
);
}
@凌驾
public int getInstanceCount(){
返回100;
}
@凌驾
公共程序getProgram(){
返回程序;
}
@凌驾
public int getDataSize(){
返回6*6;
}
@凌驾
公共浮动缓冲区putData(最终浮动缓冲区数据缓冲区){
FloatBuffer returnData=dataBuffer.put(数据);
data.clear();//清除以重置数据状态
返回数据;
}
@凌驾
public int getDataMode(){
返回GL_三角形;
}
@凌驾
公共布尔值isShadowReceiver(){
返回true;
}
@凌驾
公共布尔值isShadowCaster(){
返回true;
}
私有FloatBuffer generateBox(){
FloatBuffer-boxData=BufferUtils.createFloatBuffer(6*6*3);
//将数据放入boxData
return(FloatBuffer)boxData.clear();
}
}
首先,我将介绍如何编写此代码的步骤:
Drawable
接口开始,每个实现都有自己的drawDepthPass
、draw
和delete
方法delete
重构为default
方法很简单,也很简单,不应该出错drawDepthPass
和draw
我需要访问Drawable
是否被细分和/或实例化,所以我添加了公共(非默认的)方法IsEstessellated()
,IsInstanceCount()
可绘制的中实现它们会有点麻烦,因为我们程序员都很懒
default
方法添加到Drawable
,给出了最基本的Drawable
方法的行为TessellatedDrawable
和instancedrawable
,分别提供default
istesellated()
和isInstanced()
。在InstancedDrawable
中,我撤销了getInstanceCount()
的default
实现- 普通
:Drawable
公共A类实现Drawable
- 镶嵌
:可绘制
公共类A实现镶嵌可绘制
- Instanced
:Drawable
公共A类实现InstancedDrawable
- 细分和实例化
:可绘制
公共类A实现了InstancedDrawable、细分可绘制
实现了InstancedDrawable,TessellatedDrawable
可以被Java 8完美地处理,因为功能应该来自哪个接口是没有任何歧义的
现在我来谈谈我自己的OOP设计评估:
- 每个
实际上都是一个可绘制的
,因此可绘制的
不会中断集合
- 可以将所有的
和/或镶嵌可绘制
分组,这与它的具体实现方式无关InstancedDrawable
- 使用更传统的分层方法,但我忽略了这一点,因为它最终会导致:
抽象类AbstractDrawable
class Drawable扩展了AbstractDrawable
class TessellatedDrawable扩展了AbstractDrawable
class InstancedDrawable扩展了AbstractDrawable
class InstancedTessellatedDrawable扩展了AbstractDrawable
因此,第一个也是最后一个问题是:我是在使用Java 8的功能还是误用了它?首先,如果它有效,并且它做了您想做的事情,那么没有危险
public interface TessellatedDrawable extends Drawable {
@Override
default public boolean isTessellated() {
return true;
}
}
public interface InstancedDrawable extends Drawable {
@Override
default public boolean isInstanced() {
return true;
}
@Override
public int getInstancesCount();
}
public class Box implements TessellatedDrawable, InstancedDrawable {
//<editor-fold defaultstate="collapsed" desc="keep-imports">
static {
int KEEP_LWJGL_IMPORTS = GL_2_BYTES | GL_ALIASED_LINE_WIDTH_RANGE | GL_ACTIVE_TEXTURE | GL_BLEND_COLOR | GL_ARRAY_BUFFER | GL_ACTIVE_ATTRIBUTE_MAX_LENGTH | GL_COMPRESSED_SLUMINANCE | GL_ALPHA_INTEGER | GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH | GL_ALREADY_SIGNALED | GL_ANY_SAMPLES_PASSED | GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH | GL_ACTIVE_PROGRAM | GL_ACTIVE_ATOMIC_COUNTER_BUFFERS | GL_ACTIVE_RESOURCES | GL_BUFFER_IMMUTABLE_STORAGE;
int KEEP_OWN_IMPORTS = UNIFORM_PROJECTION_MATRIX.getLocation() | VS_POSITION.getLocation();
}
//</editor-fold>
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 int getInstancesCount() {
return 100;
}
@Override
public Program getProgram() {
return program;
}
@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);
//put data into boxData
return (FloatBuffer)boxData.clear();
}
}