5

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

(多数のうちの 1 つの実装)

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の観点からインターフェイスの実装は正しいですか。
  2. 最も基本的なDrawableものはインスタンス化されず、テッセレーションもされないことを考えると、疑似コードisTessellated() = false, isInstanced() = false, ではgetInstancesCount() = 0、そのようなプロパティを持つデフォルト メソッドを宣言することは有効でしょうか?
4

2 に答える 2

1

デフォルト メソッドの利点は、インターフェイス内のメソッドのみに基づく機能を提供するために抽象クラスを作成する必要がなくなったことです。この期間中、あなたのデザインは有効です。

詳細については、デフォルトのメソッドをご覧ください

于 2014-02-26T09:59:54.127 に答える