とりあえず雑記帳(跡地)
じゃあオブジェクト指向ならどうする?
最終更新:
fujiyan
-
view
目標
ということで、今回の目標として先に挙げた問題点の逆
- プログラムの必要最低限の知識で
- 既に動いている部分には手を加えずに
機能を拡張することを、インターフェースを活用して実現してみましょう。
拡張したい対象をインターフェースとして定義
今回、拡張したい対象は「演算」です。ということで、今回のプログラムが「演算」に求める機能を
インターフェースとして定義します。
インターフェースとして定義します。
package jp.fujiyan.binaryoperation3;
/**
* 二項演算です。
*
* @author Fujiyan
*/
public interface IBinaryOperator {
/**
* 選択時の表示に用いる文字列を返します。
*
* @return 文字列
*/
String getChoiseString();
/**
* 計算を実行します。
*
* @param value1
* @param value2
*/
void calculate(int value1, int value2);
/**
* 計算エラーが発生したかどうかを判定します。
*
* @return 計算エラーが発生しているならばtrue
*/
boolean isError();
/**
* 計算エラーが発生している場合の、エラーメッセージを返します。
*
* @return メッセージ
*/
String getErrorMessage();
/**
* 実行した計算式の文字列を返します。
*
* @return 計算式
*/
String getExpression();
/**
* 実行した計算の答えを表す文字列を返します。
*
* @return 計算の答え
*/
String getResult();
}
実装クラスを定義
先に定義したインターフェースを実装するクラスを定義します。
加算
package jp.fujiyan.binaryoperation3.operator;
import jp.fujiyan.binaryoperation3.IBinaryOperator;
/**
* 加算です。
*
* @author Fujiyan
*/
public class Addition implements IBinaryOperator {
private String expression;
private String result;
public String getChoiseString() {
return "加算";
}
public void calculate(int value1, int value2) {
expression = String.valueOf(value1) + " + " + String.valueOf(value2);
result = String.valueOf(value1 + value2);
}
public boolean isError() {
// エラーが発生することは無いので、常にfalse
return false;
}
public String getErrorMessage() {
// エラーが発生することは無いので、常にnull
return null;
}
public String getExpression() {
return expression;
}
public String getResult() {
return result;
}
}
減算
package jp.fujiyan.binaryoperation3.operator;
import jp.fujiyan.binaryoperation3.IBinaryOperator;
/**
* 減算です。
*
* @author Fujiyan
*/
public class Subtraction implements IBinaryOperator {
private String expression;
private String result;
public String getChoiseString() {
return "減算";
}
public void calculate(int value1, int value2) {
expression = String.valueOf(value1) + " - " + String.valueOf(value2);
result = String.valueOf(value1 - value2);
}
public boolean isError() {
// エラーが発生することは無いので、常にfalse
return false;
}
public String getErrorMessage() {
// エラーが発生することは無いので、常にnull
return null;
}
public String getExpression() {
return expression;
}
public String getResult() {
return result;
}
}
乗算
package jp.fujiyan.binaryoperation3.operator;
import jp.fujiyan.binaryoperation3.IBinaryOperator;
/**
* 乗算です。
*
* @author Fujiyan
*/
public class Multiplication implements IBinaryOperator {
private String expression;
private String result;
public String getChoiseString() {
return "乗算";
}
public void calculate(int value1, int value2) {
expression = String.valueOf(value1) + " × " + String.valueOf(value2);
result = String.valueOf(value1 * value2);
}
public boolean isError() {
// エラーが発生することは無いので、常にfalse
return false;
}
public String getErrorMessage() {
// エラーが発生することは無いので、常にnull
return null;
}
public String getExpression() {
return expression;
}
public String getResult() {
return result;
}
}
除算
package jp.fujiyan.binaryoperation3.operator;
import jp.fujiyan.binaryoperation3.IBinaryOperator;
/**
* 除算です。
*
* @author Fujiyan
*/
public class Division implements IBinaryOperator {
private String expression;
private String result;
private String errorMessage;
public String getChoiseString() {
return "除算";
}
public void calculate(int value1, int value2) {
if (value2 == 0) {
// 0除算
errorMessage = "0で割ることはできません。";
return;
}
expression = String.valueOf(value1) + " ÷ " + String.valueOf(value2);
result = String.valueOf(value1 / value2) + "(余り " + String.valueOf(value1 % value2) + ")";
errorMessage = null;
}
public boolean isError() {
return (errorMessage != null);
}
public String getErrorMessage() {
return errorMessage;
}
public String getExpression() {
return expression;
}
public String getResult() {
return result;
}
}
インターフェースを通じて機能を利用する部分
最後に、上記を動かす部分
/*
* オブジェクト指向版
*/
package jp.fujiyan.binaryoperation3;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import jp.fujiyan.binaryoperation3.operator.Addition;
import jp.fujiyan.binaryoperation3.operator.Division;
import jp.fujiyan.binaryoperation3.operator.Multiplication;
import jp.fujiyan.binaryoperation3.operator.Subtraction;
/**
* 二項演算です。
*
* @author fujiyan
*/
public class BinaryOperation {
// 入力値の最小
private static final int MIN_VALUE = -99999;
// 入力値の最大
private static final int MAX_VALUE = 99999;
// 選択肢
private static final int FINISH = 0;
// 演算子のリスト
private static List<IBinaryOperator> operatorList = new ArrayList<IBinaryOperator>();
static {
// operatorListの初期化
operatorList.add(new Addition());
operatorList.add(new Subtraction());
operatorList.add(new Multiplication());
operatorList.add(new Division());
}
/**
* ユーザ入力を返します。
*
* @param prompt プロンプト文
* @return ユーザ入力文字列
*/
private static String input(String prompt) throws IOException {
System.out.println(prompt);
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String str = in.readLine();
if (str == null) {
// Ctrl+Zによる中断
throw new EOFException("中断されました。");
}
return str;
}
/**
* 整数値を問い合わせます。
*
* @return 整数値
*/
private static int askValue(int seq) throws IOException {
int value = 0;
boolean invalid = true;
while (invalid) {
// 整数値が入力されるまで
String ret = input(String.valueOf(seq) + "番目の数値を入力してください(" + MIN_VALUE + "~" + MAX_VALUE + "の整数)。");
try {
value = Integer.parseInt(ret);
} catch (NumberFormatException e) {
// 整数値として有効でない文字列
System.out.println("入力された値は整数値ではありません。");
continue;
}
invalid = (value < MIN_VALUE) || (value > MAX_VALUE);
if (invalid) {
// 無効な入力
System.out.println("入力された数値が範囲を超えています。");
}
}
return value;
}
/**
* 操作を問い合わせます。
*
* @return 操作の選択肢
*/
private static int askOperation() throws IOException {
StringBuilder sb = new StringBuilder();
int i = 0;
sb.append(i).append(":").append("終了");
while (i < operatorList.size()) {
sb.append(" ");
sb.append(i + 1).append(":").append(operatorList.get(i).getChoiseString());
i++;
}
String prompt = "操作を番号で選択してください。(" + new String(sb) + ")";
int operation = 0;
boolean invalid = true;
while (invalid) {
// 有効な選択肢が入力されるまで
String ret = input(prompt);
try {
operation = Integer.parseInt(ret);
invalid = (operation < 0) || (operation > operatorList.size());
} catch (NumberFormatException e) {
// 数値として有効でない文字列
}
if (invalid) {
// 無効な入力
System.out.println("正しい番号を選択してください。");
}
}
return operation;
}
/**
* 演算を行います。
*
* @param operation 操作の選択肢
* @param value1 値1
* @param value2 値2
*/
private static void execute(int operation, int value1, int value2) {
IBinaryOperator op = operatorList.get(operation - 1);
op.calculate(value1, value2);
if (op.isError()) {
// エラーあり
System.out.println(op.getErrorMessage());
return;
}
System.out.println(op.getExpression() + " の答えは " + op.getResult() + " です。");
}
/**
* メインメソッドです。
*
* @param args コマンドライン引数
*/
public static void main(String[] args) {
try {
int operation = askOperation();
while (operation != FINISH) {
// "終了"が選択されるまで
int val1 = askValue(1);
int val2 = askValue(2);
execute(operation, val1, val2);
operation = askOperation();
}
System.out.println("終了します。");
} catch (EOFException e) {
// Ctrl+Zによる中断
System.err.println(e.getMessage());
} catch (Exception e) {
// その他例外
System.err.println("なんかまずいことが発生しました。");
e.printStackTrace();
}
}
}