字段必须是保密的,但子类必须使用此字段覆盖方法?

时间:2012-07-01 05:04:09

标签: java

我遇到了设计问题:

  • 问题类:有问题和回答(String)
  • TextQuestion类:普通文本问答
  • NumberQuestion类:question(String),answer(number - int,float ...),并使用epsilon值检查答案

但我对NumberQuestion有疑问。我必须采取正确的答案,将其转换为数字,并与用户的答案进行比较。那么我该如何得到答案呢?使用getter方法并不安全。或者我的设计不好?我怎样才能改变?

public abstract class Question {
  private String question;
  private String answer;

  public Question(String question, String answer) {
      this.question = question;
      this.answer = answer;
  }

  public boolean checkAnswer(String yourAnswer) {
      // default implementation
  }
}

class TextQuestion extends Question {
  // Answer and Question is always string type, it's OK, not problem
}

class NumberQuestion extends Question {
  // Question is String, OK
  // Answer: input is number, accept approximately
  // Ex: Question: 1/3 = ?
  //     Answer: 0.3 or 0.33 or 0.333 are accepted (using an Epsilon value)

  // so must override checkAnswer
  public boolean checkAnswer(String yourAnswer) {
      // HOW can I do?
  }
}

3 个答案:

答案 0 :(得分:4)

我不明白为什么你需要从子类(或任何客户端代码)隐藏答案。客户端代码肯定需要首先知道答案才能创建TextQuestionNumberQuestion实例。

您应该从Question类中抽象出测试的逻辑以及答案类型:

public abstract class Question<AnswerType> {
  private String question;
  private AnswerType answer;

  public Question(String question, AnswerType answer) {
    this.question = question;
    this.answer = answer;
  }

  public abstract boolean checkAnswer(AnswerType yourAnswer);

  protected AnswerType getAnswer() {
    return answer;
  }
}

class TextQuestion extends Question<String> {
  public TextQuestion(String question, String answer) {
    super(question, answer);
  }

  public boolean checkAnswer(String yourAnswer) {
    return answer.equals(yourAnswer);
  }
}

class NumberQuestion extends Question<Double> {
  private double epsilon;

  public NumberQuestion(String question, Double answer, double epsilon) {
    super(question, answer);
    this.epsilon = epsilon;
  }

  public boolean checkAnswer(Double yourAnswer) {
    return Math.abs(getAnswer() - yourAnswer) < epsilon;
  }
}

答案 1 :(得分:1)

如果您的答案可以有不同的类型,您也可以在抽象类中使用泛型。

public abstract class Question<T> {
    private final String question;
    protected final T answer;

    public Question(String question, T answer) {
        this.question = question;
        this.answer = answer;
    }

    //Default implementation
    public boolean checkAnswer(T yourAnswer) {
        return answer.equals(yourAnswer);
    }
}

当您定义子类时:

class NumberQuestion extends Question<BigDecimal> {
    ...
    private final BigDecimal epsilon;

    public NumericQuestion(String question, BigDecimal answer, BigDecimal epsilon) {
        super(question, answer);

        this.epsilon = epsilon;
    }

    @Override
    public boolean checkAnswer(BigDecimal yourAnswer) {
        BigDecimal result = this.answer.subtract(yourAnswer).abs();

        return (result.compareTo(epsilon) == -1); // check whether result < epsilon
    }
}

顺便说一下,使用BigDecimal进行浮点计算,而不是更好。有很多关于此的好文章。如果您对此感兴趣,可以“谷歌”这个问题。

如果需要设置浮点数的比例,可以使用大小数字轻松完成此操作,例如:

result = result.setScale(5);

请注意,因为BigDecimal类是不可变的(不完全,但这是另一个问题)并在您尝试更改其状态时返回新实例。

答案 2 :(得分:0)

我不确定你是否熟悉泛型类,但在这种情况下这是合适的。你可以谷歌吧。 : - )

如果您不想这样做,您可以随时将yourAnswerthis.answer转换为相同的类型,然后您可以找到绝对差异,并确保它们低于特定的阈。