java - 使用带有默认方法的新 Java8 接口(interface)

标签 java oop interface java-8 default-method

我有几个关于 Java 8 中"new"接口(interface)的问题,我有以下代码:

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);
    }
}

(一个实现多个)

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();
    }
}

问题:

  1. 从 OOP 的角度来看,接口(interface)的实现是否正确,尤其是考虑到我通过公共(public) getter 来“存储/访问数据”这一事实。
  2. 考虑到最基本的Drawable不会被实例化,也不会被镶嵌,所以在伪代码中isTessellated() = false, isInstanced() = false getInstancesCount() = 0,声明具有此类属性的默认方法是否有效?

最佳答案

关于默认方法的事情是你不再被迫创建一个抽象类来提供一些仅基于接口(interface)中的方法的功能。在这个术语中,您的设计是有效的。

更多请访问Default Methods

关于java - 使用带有默认方法的新 Java8 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22037263/

相关文章:

java - Elasticsearch JEST 日期序列化 java

java - 数据库同步技术JPA/GUI

c++ - 覆盖另一种方法使用的父类(super class)回调函数[C++]

java - 在java中实现接口(interface)和抽象类中都存在的方法

java - 为什么方法的通用返回类型无效

java - 创建 Java DatagramSocket 对象时为 "address already in use cannot bind"。

java - 我们可以在 xml 中为 android 背景制作多色渐变吗?

c# - 在 .net 中转换期间对象会发生什么变化?

java - 覆盖/禁用 super 接口(interface)方法

interface - 我如何访问 Clojure 库中的记录?