2016-05-15 42 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同意。只是用我认为更好的选择更新了答案。 –