skiwi
skiwi

Reputation: 69379

Using the new Java8 interface with default methods

I have a few questions about the 'new' interfaces in Java 8, I have the following code:

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

(one implementation of many)

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

The questions:

  1. Is the implementing of the interface correct from an OOP perspective, especially with the fact that I 'store/access data' via public getters.
  2. Considering that the most basic Drawable will not be instanced and neither be tessellated, so in psuedo code isTessellated() = false, isInstanced() = false, getInstancesCount() = 0, would it be valid to declare default methods with such properties?

Upvotes: 5

Views: 342

Answers (2)

The thing about defaults method is that you are not longer forced to create a abstract class to deliver some functionality that is based only on the method that are in the interfaces. In this term your design is valid.

For more please visit Default Methods

Upvotes: 1

Tim B
Tim B

Reputation: 41208

What you have done does seem as though it should be valid (I've not really used the Java 8 stuff yet but I'm aware of it), however it is not really the best object oriented design.

This would be better done as an abstract class that you extend (especially since Box doesn't extend anything but implements drawable) since then you can also store the data within the class as well as having the methods to implement it.

As it is now the methods might as well be in a static utility class for all the use they are making of being inside the class. (I know they call isTesselated but a static utility class could do that too).

Upvotes: 0

Related Questions