Java의 파생 클래스 생성자 내에서 기본 클래스의 최종 변수를 어떻게 할당하려면 어떻게해야합니까?
-
20-09-2019 - |
문제
나는 기지가 있습니다 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);
}