So this is mainly a Design/Clean Coding sort of question, I know I've read something about this previously but I can't find it, I believe it's in one of my reference books on C/C++ so it wouldn't likely be useful to my predicament.
This question includes a lot of Java code because it seems to be the best way to illistrate what I'm trying to do.
I'm working on a program in Java (so no Operator overloading, which the book I mentioned used). I'm working to isolate the types of data from a buffer class I'm trying to make. The buffers should all be compatable with each other but they can hold any arbitrary object that's a sub-class of my BufferValue
interface and Comparable
. BufferValue
is defined:
/*
* Copyright © 2012 William Peckham
*/
package paint.buffers;
/**
* A base class for values that can be put into a paint.buffers.Buffer.
* An implementer should also override equals and hashCode accordingly
* @author William Matrix Peckham
*/
public interface BufferValue<T>{
/**
* gets the value
*/
public T getValue();
/**
* sets the value
* @param new value
* @return previous value
*/
public T setValue(T v);
/**
* sets the value
* @param new value
* @return previous value
*/
public BufferValue<T> setValue(BufferValue<T> v);
/**
* Add a value to this one
* @param second value to add
* @return result of addition
*/
public BufferValue<T> add(BufferValue<T> second);
/**
* Subtract a value from this one
* @param second value to subtract
* @return result of the subtraction
*/
public BufferValue<T> sub(BufferValue<T> second);
/**
* Multiply a value with this one
* @param second value to be multiplied
* @return result of the multiplication
*/
public BufferValue<T> mul(BufferValue<T> second);
/**
* Divide this by another value
* @param second value to divide by
* @return result of the division
*/
public BufferValue<T> div(BufferValue<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 BufferValue<T> normalize(BufferValue<T> min, BufferValue<T> max);
/**
* Multiply this value by a double
* @param t
* @return
*/
public BufferValue<T> mul(double t);
}
but I would like to be able to remove the <T>
from the math functions, so that any BufferValue
could be multiplied or added to any other BufferValue
. The issue being the implementation, with current things looking like:
/*
* Copyright © 2012 William Peckham
*/
package paint.buffers;
/**
*
* @author William Matrix Peckham
*/
public class DoubleValue implements BufferValue<Double>, Comparable<DoubleValue>{
Double value;
public DoubleValue(){
value=0.0;
}
public DoubleValue(Double f){
value=f;
}
@Override
public BufferValue<Double> add(BufferValue<Double> second){
return new DoubleValue(value+second.getValue());
}
@Override
public BufferValue<Double> sub(BufferValue<Double> second){
return new DoubleValue(value-second.getValue());
}
@Override
public BufferValue<Double> mul(BufferValue<Double> second){
return new DoubleValue(value*second.getValue());
}
@Override
public BufferValue<Double> div(BufferValue<Double> second){
return new DoubleValue(value/second.getValue());
}
@Override
public BufferValue<Double> normalize(BufferValue<Double> min, BufferValue<Double> max){
return new DoubleValue(((value-min.getValue())/(max.getValue()-min.getValue()))+min.getValue());
}
@Override
public int compareTo(DoubleValue o) {
return new Double(value).compareTo(o.value);
}
@Override
public boolean equals(Object o){
if(o instanceof DoubleValue){
return new Double(value).equals(new Double(((DoubleValue)o).value));
}
return false;
}
@Override
public int hashCode(){
return new Double(value).hashCode();
}
@Override
public Double getValue() {
return value;
}
@Override
public BufferValue<Double> setValue(BufferValue<Double> v) {
Double d = value;
value=v.getValue();
return new DoubleValue(d);
}
@Override
public Double setValue(Double v) {
Double vr = value;
value=v;
return vr;
}
@Override
public BufferValue<Double> mul(double t) {
return new DoubleValue(t*value);
}
}
and
/*
* Copyright © 2012 William Peckham
*/
package paint.buffers;
import java.awt.Color;
/**
*
* @author William Matrix Peckham
*/
public class ColorValue implements BufferValue<Color>, Comparable<ColorValue>{
Color value;
public ColorValue(){
value=new Color(0,0,0);
}
public ColorValue(Color c){
value=c;
}
@Override
public BufferValue<Color> add(BufferValue<Color> second) {
float[] comps = value.getRGBComponents(null);
float[] comps1 = second.getValue().getRGBComponents(null);
float[] rets = new float[4];
for(int i = 0; i<4; i++){
rets[i]=comps[i]+comps1[i];
}
return new ColorValue(new Color(rets[0], rets[1], rets[2], rets[3]));
}
@Override
public BufferValue<Color> sub(BufferValue<Color> second) {
float[] comps = value.getRGBComponents(null);
float[] comps1 = second.getValue().getRGBComponents(null);
float[] rets = new float[4];
for(int i = 0; i<4; i++){
rets[i]=comps[i]-comps1[i];
}
return new ColorValue(new Color(rets[0], rets[1], rets[2], rets[3]));
}
@Override
public BufferValue<Color> mul(BufferValue<Color> second) {
float[] comps = value.getRGBComponents(null);
float[] comps1 = second.getValue().getRGBComponents(null);
float[] rets = new float[4];
for(int i = 0; i<4; i++){
rets[i]=comps[i]*comps1[i];
}
return new ColorValue(new Color(rets[0], rets[1], rets[2], rets[3]));
}
@Override
public BufferValue<Color> div(BufferValue<Color> second) {
float[] comps = value.getRGBComponents(null);
float[] comps1 = second.getValue().getRGBComponents(null);
float[] rets = new float[4];
for(int i = 0; i<4; i++){
rets[i]=comps[i]/comps1[i];
}
return new ColorValue(new Color(rets[0], rets[1], rets[2], rets[3]));
}
@Override
public BufferValue<Color> normalize(BufferValue<Color> min, BufferValue<Color> max) {
return new ColorValue(value);
}
@Override
public int compareTo(ColorValue o) {
int xi = (new Integer(value.getAlpha())).compareTo(o.value.getAlpha());
if (xi == 0) {
xi = (new Integer(value.getRed())).compareTo(o.value.getRed());
if (xi == 0) {
xi = (new Integer(value.getGreen())).compareTo(o.value.getGreen());
if (xi == 0) {
xi = (new Integer(value.getBlue())).compareTo(o.value.getBlue());
}
}
}
return xi;
}
@Override
public boolean equals(Object o){
if(o instanceof ColorValue){
return value.equals(((ColorValue)o).value);
}
return false;
}
@Override
public int hashCode(){
return value.hashCode();
}
@Override
public Color getValue() {
return value;
}
@Override
public BufferValue<Color> setValue(BufferValue<Color> v) {
Color d = value;
value=v.getValue();
return new ColorValue(d);
}
@Override
public Color setValue(Color v) {
Color vr = value;
value=v;
return vr;
}
@Override
public BufferValue<Color> mul(double t) {
float[] comps = value.getRGBComponents(null);
float[] rets = new float[4];
for(int i = 0; i<4; i++){
rets[i]=(float)(comps[i]*t);
}
return new ColorValue(new Color(rets[0], rets[1], rets[2], rets[3]));
}
}
The issue of adding a single double to the Color I'd like to solve by adding the value to all the individual components. How can I make it so I can implement type-type operations like this without having an exponential number of implementations, and without expressly stating which value is being used (BufferValue<Color> ColorBuffer.add(BufferValue<Double>)
, BufferValue<Color> DoubleBuffer.add(BufferValue<Color>)
, BufferValue<Color> ColorBuffer.add(BufferValue<Color>)
, BufferValue<Double> DoubleBuffer.add(BufferValue<Double>)
).