Java의 파생 클래스 생성자 내에서 기본 클래스의 최종 변수를 어떻게 할당하려면 어떻게해야합니까?

StackOverflow https://stackoverflow.com/questions/1734377

문제

나는 기지가 있습니다 Color 이렇게 보이는 수업. 이 수업은 불변으로 설계되었으므로 결과적으로 final 수정 자 및 세터 없음 :

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
}

이 수업에서 파생 된 것은 a입니다 ColorHSL 제공하는 것 외에도 수업 Color 클래스의 getters는 색조, 채도 및 광도에 기여합니다. 이것은 일이 작동하지 않는 곳입니다.

생성자 ColorHSL 계산을 수행 한 다음 값을 설정해야합니다. _r, _b, 그리고 _g. 그러나 슈퍼 생성자를 호출해야합니다 ~ 전에 계산이 이루어집니다. 그래서 매개 변수가 없습니다 Color() 생성자가 도입되어 최종적으로 허용됩니다 _r, _b, 그리고 _g 나중에 설정해야합니다. 그러나, 매개 변수가없는 생성자 또는 설정 (처음으로 생성자 내에서 처음으로 ColorHSL)는 Java 컴파일러에 의해 허용됩니다.

이 문제에 대한 방법이 있습니까? 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;
    }
}

클래스 RGBColor 그리고 HSLColor 그런 다음 파생 Color, 초기화하는 간단한 생성자를 구현합니다 RGBValues 그리고 HSLValues 회원. (예, 기본 클래스가 파생 클래스의 정적 인스턴스를 포함한다는 것을 알고 있습니다)

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);
    }
}
도움이 되었습니까?

해결책

예, 방법을 알 수 있습니다 super(calculateRGB(...)) - 하지만 여기에서 상속에서 실질적으로 아무것도 얻지 못하는 것처럼 보입니다.. 공통 인터페이스 만 사용합니다. RGB와 HSV는 서로 다른 두 개의 서로 교환 가능한 색상 모델이 아닌가?

Java 문제 뒤에 객체 지향 분석 문제가 있다고 생각합니다. 상속을 사용하는 이유는 무엇입니까?

당신이해야 할 일은 색상을 상호 교환 적으로 조작하는 것입니다. 상속에서 전혀 도움이되지 않는다는 것을 알 수 있습니다. (그리고 슈퍼 클래스의 경우 HSV를 RGB로 다시 매핑하는 오버 헤드를 만듭니다) ... 상호 교환 가능한 색상 모델을 원한다면 RGB에서 상속하는 대신 색 인터페이스를 사용하는 것을 고려하십시오.

실제로 컬러 객체를 사용하는 것을 보지 않으면 더 나은 디자인을 제안하기가 어렵습니다. 지금은 상속 비용 (슈퍼 생성자로의 컬러 모델 변환)이 재사용의 유일한 혜택을 능가하는 것처럼 보입니다. normalize.

다른 팁

선언 유형의 생성자가 완료 될 때까지 최종 변수를 할당해야합니다. 따라서 서브 클래스에 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);
    }
}

내가이 작업을 수행 할 수있는 유일한 방법은 슈퍼 생성자의 호출을 R, G 및 B를 계산하는 기능으로 중첩하는 것입니다.

super(calculateRGB(...))

따라서 RGB 값을 배열로 사용하는 생성자를 색상에 추가하는 것을 고려할 수 있습니다.

Java에는 추상 생성자를 가질 수 없으므로 모든 계산을 슈퍼로 통화에 넣을 수 없다면 현재 디자인으로 수행하고 싶은 일을 수행 할 수 없습니다. 최종 변수는 시간에 따라 할당해야합니다. 선언 생성자가 완료되었습니다.

대안은 인수를 취하는 컬러 객체 (공장 패턴)의 생성을위한 몇 가지 방법을 고려하는 것입니다.

예를 들어 - 색상 클래스에 다음이있는 경우

public Color static createHSLColor(int h, int s, int v) {
   // All the calculation here

   return new ColorHSL(h,s,v);
}

그런 다음 생성자를 공개하지 않고 (보호 될 수 있음) 객체를 생성 할 수있는 유일한 방법은 공장 방법을 통한 것입니다.

당신이 할 수있는 한 가지는 계산기를 나타내는 생성자 매개 변수를 갖는 것입니다. 예를 들어 :

public Color(int r, int g, int b, Calc calc) {
   _r = calc.normalize(r);
   _g = calc.normalize(g);
   _b = calc.normalize(b);
}

이것은 서브 클래스의 필요성을 완전히 제거 할 수 있습니다. 생성자를 선언 할 수 있습니다.

public Color(int r, int g, int b) { 
  this(r,g,b, defaultCalc);
}

또는 정적 스타일 생성자를 제공합니다.

public static Color hslColor(int r, int g, int b) {
    return new Color(r,g,b, hslCalc);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top