2016-05-15 90 views
1

比方說,我們有一個抽象類,定義構造函數取其中的一個先決條件檢查,如果該整數爲可能值的列表內的整數:如何初始化子類中的靜態成員?

public abstract class Value { 
    protected int value; 
    protected static List<Integer> possibleValues; 

    public Value(int val) { 
     if (!possibleValues.contains(val)) 
      throw new IllegalArgumentException("Illegal value"); 
     value = val; 
    } 
} 

但我們要初始化Value的孩子該列表因爲每個類都定義了自己的可能值列表。

我想我可以做一個static塊添加成員possibleValues,雖然我不喜歡static塊。但這並不意味着所有的孩子班級都會停止指向相同的可能值列表。

如何強制兒童班級定義可能的值列表並進行前提條件檢查而不面臨我描述的問題?

編輯:所以我們可以說我想繼承行爲而不是變量本身。

+0

你爲什麼不定義一個抽象'isValid'方法子類填?或者使用派生類提供的ValueChecker類對值進行模板化? – Robert

+0

我建議使用Set而不是List。此外,使用工廠模式將更加可用和更清潔。 –

回答

2

如何:

public abstract class Value { 
    protected int value; 
    protected abstract List<Integer> getPossibleValues(); 

    public Value(int val) { 
     if (!getPossibleValues().contains(val)) 
      throw new IllegalArgumentException("Illegal value"); 
     value = val; 
    } 
} 

你的子類將被強制執行getPossibleValues()

+2

一般的想法很好,但在這裏你有一個構造函數調用子類重寫的方法,這是一個壞主意:http://stackoverflow.com/questions/3404301/whats-wrong-with-overridable-method-calls-in-建設者 –

+0

@dabadaba:這只是我頭頂的一個想法。正如奧利弗所指出的那樣,這不是最好的想法,一定能找到更好的設計。 – Burkhard

+0

@Oliver它會做到目前爲止,因爲父類不會被繼承。我有絕對的控制權。但出於好奇,你會建議什麼替代方案? – dabadaba

0

如何像:

public abstract class Value { 
    int value; 

    protected Value(int val, List<Integer> possibleValues) { 
     if (!possibleValues.contains(val)) { 
      throw IllegalArgumentException(); 
     } 
     this.value = val; 
    } 
} 

class SubValue extends Value { 
    private static final List<Integer> possibleValues = ...; 
    SubValue(int val) { 
     super(val, possibleValues); 
    } 
} 
+0

他們爲什麼會記得這麼做?我的設計的重點是在父類中包含行爲(先決條件檢查),以便子類不必這樣做。 – dabadaba

+0

@dabadaba同意。只是用我認爲更好的選擇更新了答案。 –