I have a base Color
class that looks something like this. The class is designed to be immutable, so as a result has final
modifiers and no setters:
public class Color
{
public static Color BLACK = new Color(0, 0, 0);
public static Color RED = new Color(255, 0, 0);
//...
public static Color WHITE = new Color(255, 255, 255);
protected final int _r;
protected final int _g;
protected final int _b;
public Color(int r, int b, int g)
{
_r = normalize(r);
_g = normalize(g);
_b = normalize(b);
}
protected Color()
{
}
protected int normalize(int val)
{
return val & 0xFF;
}
// getters not shown for simplicity
}
Derived from this class is a ColorHSL
class that in addition to providing the Color
class' getters, is contructed with hue, saturation, and luminosity. This is where things stop working.
The constructor of ColorHSL
needs to do some calculations, then set the values of _r
, _b
, and _g
. But the super constructor has to be called before any calculations are made. So the parameterless Color()
constructor was introduced, allowing the final _r
, _b
, and _g
to be set later on. However, neither the parameterless constructor or the setting (for the first time, within the constructor of ColorHSL
) are accepted by the Java compiler.
Is there a way around this issue, or do I have to remove the final
modifier from _r
, _b
, and _g
?
Edit:
In the end, I went for a base abstract Color
class, containing both RGB and HSL data. The base class:
public abstract class Color
{
public static Color WHITE = new ColorRGB(255, 255, 255);
public static Color BLACK = new ColorRGB(0, 0, 0);
public static Color RED = new ColorRGB(255, 0, 0);
public static Color GREEN = new ColorRGB(0, 255, 0);
public static Color BLUE = new ColorRGB(0, 0, 255);
public static Color YELLOW = new ColorRGB(255, 255, 0);
public static Color MAGENTA = new ColorRGB(255, 0, 255);
public static Color CYAN = new ColorRGB(0, 255, 255);
public static final class RGBHelper
{
private final int _r;
private final int _g;
private final int _b;
public RGBHelper(int r, int g, int b)
{
_r = r & 0xFF;
_g = g & 0xFF;
_b = b & 0xFF;
}
public int getR()
{
return _r;
}
public int getG()
{
return _g;
}
public int getB()
{
return _b;
}
}
public final static class HSLHelper
{
private final double _hue;
private final double _sat;
private final double _lum;
public HSLHelper(double hue, double sat, double lum)
{
//Calculations unimportant to the question - initialises the class
}
public double getHue()
{
return _hue;
}
public double getSat()
{
return _sat;
}
public double getLum()
{
return _lum;
}
}
protected HSLHelper HSLValues = null;
protected RGBHelper RGBValues = null;
protected static HSLHelper RGBToHSL(RGBHelper rgb)
{
//Calculations unimportant to the question
return new HSLHelper(hue, sat, lum);
}
protected static RGBHelper HSLToRGB(HSLHelper hsl)
{
//Calculations unimportant to the question
return new RGBHelper(r,g,b)
}
public HSLHelper getHSL()
{
if(HSLValues == null)
{
HSLValues = RGBToHSL(RGBValues);
}
return HSLValues;
}
public RGBHelper getRGB()
{
if(RGBValues == null)
{
RGBValues = HSLToRGB(HSLValues);
}
return RGBValues;
}
}
The classes of RGBColor
and HSLColor
then derive from Color
, implementing a simple constructor that initializes the RGBValues
and HSLValues
members. (Yes, I know that the base class if-ily contains a static instance of a derived class)
public class ColorRGB extends Color
{
public ColorRGB(int r, int g, int b)
{
RGBValues = new RGBHelper(r,g,b);
}
}
public class ColorHSL extends Color
{
public ColorHSL(double hue, double sat, double lum)
{
HSLValues = new HSLHelper(hue,sat,lum);
}
}