如何在Java中的派生类'构造函数中分配基类的最终变量?

Eri*_*ric 0 java inheritance final immutability

我有一个Color看起来像这样的基类.该类被设计为不可变的,因此结果具有final修饰符且没有setter:

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
}
Run Code Online (Sandbox Code Playgroud)

从这个类衍生出来的ColorHSL类除了提供Color类'getter之外,还具有色调,饱和度和亮度.这是事情停止工作的地方.

的构造ColorHSL需要做一些计算,然后设置的值_r,_b_g.但是在进行任何计算之前必须调用超级构造函数.因此,无参数Color()的构造函数被引入,允许最终_r,_b以及_g稍后的设置.但是,ColorHSLJava编译器都不接受无参数构造函数或设置(第一次在构造函数中).

有没有解决这个问题的一种方式,还是我不得不删除final的来自调节剂_r,_b_g


编辑:

最后,我选择了一个基本抽象Color类,包含RGB和HSL数据.基类:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

的类RGBColorHSLColor然后从推导Color,实现一个简单的构造函数初始化RGBValuesHSLValues成员.(是的,我知道基类if-ily包含派生类的静态实例)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

mer*_*ike 8

必须在声明类型的构造函数完成时指定最终变量.因此,您不能在子类中指定super的最终字段.

但是,您可以在子类中的静态工厂方法中进行转换:

class HSLColor {
    private HSLColor(int r, int g, int b) { super(r,g,b);}

    static HSLColor create(int h, int s, int l) {
        // conversion code here
        return new HSLColor(r,g,b);
    }
}
Run Code Online (Sandbox Code Playgroud)