1

設計上の問題があります:

  • 質問クラス: 質問と回答があります (文字列)
  • TextQuestion クラス: 通常のテキストの質問と回答
  • NumberQuestion クラス: 質問 (文字列)、回答 (数値 - int、float...)、イプシロン値を使用した回答の確認

しかし、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?
  }
}
4

3 に答える 3

4

サブクラスから (またはクライアント コードから) 回答を非表示にする必要がある理由がわかりません。TextQuestionクライアント コードは、 orNumberQuestionインスタンスを作成するために、最初に答えを知る必要があります。

テストのロジックと回答タイプを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;
  }
}
于 2012-07-01T05:31:43.523 に答える
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 を使用する方が良いです。これについては良い記事がたくさんあります。この質問が興味深い場合は、この質問を「ググる」ことができます。

浮動小数点数の位取りを設定する必要がある場合は、大きな 10 進数で簡単に設定できます。次に例を示します。

result = result.setScale(5);

また、 BigDecimal クラスは不変であり(完全ではありませんが、これは別の質問です)、状態を変更しようとすると新しいインスタンスが返されるため、注意してください。

于 2012-07-01T05:20:37.833 に答える
0

ジェネリック クラスに精通しているかどうかはわかりませんが、この場合は適切でしょう。あなたはそれをグーグルすることができます。:-)

それをしたくない場合は、いつでも と の両方yourAnswerthis.answer同じタイプに変換できます。その後、絶対的な違いを見つけて、それらが特定のしきい値よりも低いことを確認できます。

于 2012-07-01T05:11:59.240 に答える