Hello all, been a while since I've asked a question. I'm working on a project just to practice and for fun and I've run into a snag.

I'm working on a painting type program and I'm trying to get a generic Buffer class for the images so I can use it for single float values like an alpha channel, or for a whole java.awt.Color. I'm setting up an interface for what the buffers will hold so that in any case I could call buffer.setPixel(x,y,buffer.getPixel(x,y).add(new ColorValue());

This is the interface I would like for BufferValue<T>:

/*
 * Copyright © 2012 William Peckham
 */
package paint.buffers;

/**
 * A base class for values that can be put into a paint.buffers.Buffer.
 * @author William Matrix Peckham
 */
public interface BufferValue<T> extends Comparable<T>{
    /**
     * Add a value to this one
     * @param second value to add
     * @return result of addition
     */
    public T add(T second);

    /**
     * Subtract a value from this one
     * @param second value to subtract
     * @return result of the subtraction
     */
    public T sub(T second);

    /**
     * Multiply a value with this one
     * @param second value to be multiplied
     * @return result of the multiplication
     */
    public T mul(T second);

    /**
     * Divide this by another value
     * @param second value to divide by
     * @return result of the division
     */
    public T div(T second);

    /**
     * get a normalized value of this one based on the minimum and maximums
     * @param min minimum
     * @param max maximum
     * @return normalized result
     */
    public T normalize(T min, T max);

    /**
     * Return a value interpolated between first and second based on a.
     * @param a interpolation parameter
     * @param first first value to interpolate between
     * @param second second value to interpolate between
     * @return the intermediate value
     */
    //WON'T COMPILE
    public static T lerp(double a, T first, T second);
}

The buffer class definition looks like this: public class Buffer<T extends BufferValue>{....}Then to implement floats would look like this:

public class FloatValue implements BufferValue<Float>{
    float value;
    public FloatValue(float f){
        value=f;
    }
    public Float add(Float second){
        return value+second;
    }
    public Float sub(Float second)//TRIVIAL IMPLEMENTATION
    public Float mul(Float second)//TRIVIAL IMPLEMENTATION
    public Float div(Float second)//TRIVIAL IMPLEMENTATION
    public Float normalize(Float min, Float max){
        return ((value-min)/(max-min))+min;
    }
    //WON'T COMPILE
    public static Float lerp(double a, Float first, Float second){
        return (1-a)*first+a*second;
    }
}

NOTE: implemented hastely and probably wrong but should give the idea

I know that the last method is not possible for a number of reasons, static methods are not allowed in interfaces and if they were generic types cannot be used in static methods. but the reason that lerp can't be made with the other functions is because a java.awt.Color implementaiton couldn't must multiply the double a...

Can someone suggest an alternative to this method that might work? I have a feeling theres a better way that I'm missing.
Off-Topic: I miss operator overloading when I work in java, it would solve this problem outright

Edited 4 Years Ago by sciwizeh: clarification

Thanks for the response,

That is undoubtably an idea, the reason I would prefer not to is: which object is the object it's called upon? the maximum, minimum, or the value to be assigned, or a dummy object? the static version just appeals to me because it would beValue v = Value.lerp(a,v1,v2) but with nonstatic I need to make the descision about whether the same thing abounts to Value v = v1.lerp(a,v2); OR Value v = v2.lerp(a,v1); OR Value v; v.lerp(a,v2,v2); OR Value dumb=new Value(); Value v = dumb.lerp(a,v1,v2); the second to last option is probably the one i'll go with but as I mentioned the static version seems the best option to me, although the first option is similar. Which would you recommend?

I don't like making design decisions without input from other people, even though I doubt anyone will ever see or use this code, it's better safe than sorry, maybe someday I will release it and people will be interrested. I'm not extreamly experienced in software design so my thoughts on the way things should work are probably not the accepted normals.

I would prefer the static method, and possibly information on how I could work around the issue if another such situation occurs.

Edited 4 Years Ago by sciwizeh: thought of another example

I agree with your reasons for wanting it to be static. Apparently there was a plan to introduce static methods in interfaces in Java 7.1, but that it has been abandoned beacuse of "technical difficulties". Because static methods can't be overridden (just masked) and are resolved at compile time yu would have a real problem knwoing which class name to use to invoke it anyway.
IMHO the best of an unsatisfactory set of options is to declare it exactly like you would if it were static, and not care which instance is used to invoke it.
Maybe ~s.o.s~ can help here - he understands the subtle details of Java better than anyone else I know.

That's a good idea i could do it that way, it just seems like a poor design to do it that way.

~s.o.s~ has always given me good advice, here, so I hope he can give some input.

I was thinking maybe there's some sort of Reflection-y thing I could do but that would be real messy.

In the meantime I'll use your idea to procede with my project. Unfortunately this may be an unsolvable problem in Java, or at least an elegant solution my be impossible.

Edited 4 Years Ago by sciwizeh: format fixing

I don't know exactly how you propose to use the given interfaces or how they fit in the big picture of your application so take this as a generic observation/food for thought about the way current code stands. :)

IMHO you are facing problems here with structuring code since the abstraction is leaking out a little bit. You create BufferValue class to abstract out how buffers work for floats, colors etc. but expose the internal type T when doing operations. Your operations return T which make it difficult to chain opeartions or work at an involved level with the returned results since there is no bound specified for T. With the current design, you'll also face issues when interoperating with different BufferValue's since the return type is T which is different for FloatBufferValue and AwtColorBufferValue.

Now back to your question: the lerp method sounds like a good candidate for the helper class which normally accompanies a widely used interface. For e.g. java.util.Collections used for manipulating and housing utility methods of the java.util.Collection classes. For e.g. one implementation can look like:

class BuffersValues {
    public static <T> BufferValue<T> lerp(double a, BufferValue<T> first, BufferValue<T> second) {
        // something here
    }
}

Now we have a problem here; we need a way for double values to interact with the containers of the BufferValue class, namely Float and Color. There are a few solutions which spring to mind:

  • Wrap the double value in a DoubleBufferValue and use the mul/add/etc. methods
  • Change double to float and re-use the FloatBufferValue
  • Add companion methods to the BufferValue interface which take float/double. For e.g. add a new mul method which accepts a double which would act as a counterpart for the regular mul method.

The route which we take depends on how you'd want the different BufferValue interface instances to interact. Is it possible for different types of buffer values to interact with each other seamlessly? Are BufferValue instances guaranteed to operate in isolation?

If all BufferValue does is provide a wrapper for data types which support numeric computation in terms of double's, make the interface implement doubleValue method which makes it easy to do computations without writing the wrapper add/mul methods.

Few possibilities:

First:

// Everything in term of BufferValue<T> for any type T; but makes it difficult
// to interoperate across different types of buffers
interface BufferValue<T> extends Comparable<T> {
    public BufferValue<T> add(BufferValue<T> second);
    public BufferValue<T> sub(BufferValue<T> second);
    public BufferValue<T> mul(BufferValue<T> second);
    public BufferValue<T> div(BufferValue<T> second);
    public BufferValue<T> normalize(BufferValue<T> min, BufferValue<T> max);
    public T getValue();
}

Second:

// Good interoperability with other BufferValues but difficult to get access
// to the underlying original value (Float or Color in your case)
interface BufferValue {
    double getDoubleValue();
    public BufferValue add(BufferValue second);
    public BufferValue sub(BufferValue second);
    public BufferValue mul(BufferValue second);
    public BufferValue div(BufferValue second);
    public BufferValue normalize(BufferValue min, BufferValue max);
}

Of course, there are other representations which might make more sense or would be more performant/shorter but without more code or knowing how this is used in real code, I can't help a lot.

Edited 4 Years Ago by ~s.o.s~

As usual you make a good point, I did indeed intend to hide the type, in an implementation blunder I didn't realize. Your first implementation is probably closer to what I need, as for adding multiplying by a double, that's a good idea, it would make the lerp possible without a method.

As that was the problem at hand I suppose that means I can mark this as solved though I'm sure i'll hit another snag soon, it'll likely be unrelated to this particularity of java.

This question has already been answered. Start a new discussion instead.