Scalaを勉強してみる#1

**Apache SparkでわちゃわちゃしたいがScalaがわからんのでとりあえずScalaの勉強**

#**Scala IDE の設定**

eclipse 4.4 以上
http://download.scala-ide.org/sdk/lithium/e44/scala211/stable/site

バージョンが合わないと
scalaエディタ展開時に下記のエラーになる。
failed to create the part's controls

他は特に詰まることなく設定できるはず。。。

#四則演算とか作ってみる
Scalaの実装したことないのでとりあえず練習。
会社の新人がやる課題で『Javaで四則演算』てのがあったのでそれをScalaでやってみる。

1. 標準入力で受け付けた値で足し算、引き算、掛け算、割り算を決める。
2. 標準入力から2つ値を取得する
3. 1で決めた計算方法で2つの値を計算する
4. 計算結果を表示する

という単純な仕様。
どんなもんになるのかやってみる。

四則演算trait。
traitはJavaでいうところのインターフェイスという認識でええんかな。

```scala:FourOperation.scala
trait FourOperation {
    val ADD_OPERATION = 1;
    val SUBTRACT_OPERATION = 2;
    val MULTIPLICATION_OPERATION = 3;
    val DIVISION_OPERATION = 4;
    val ADD_OPERATION_NAME = "加算";
    val SUBTRACT_OPERATION_NAME = "減算";
    val MULTIPLICATION_OPERATION_NAME = "乗算";
    val DIVISION_OPERATION_NAME = "除算";
    var result : Int
    var first : Int
    var second : Int
    def doOperation(first : Int, second : Int )
    def getOperationName() : String
    def getOperationMode() : Int
}
```

サブクラスで足し算、引き算、掛け算、割り算を表す。
足し算

```scala:AddOperation.scala
class AddOperation() extends FourOperation {

    var first = 0;
    var second = 0;
    var result = 0;

    def doOperation(first : Int , second : Int) {
        this.first = first;
        this.second = second;
        result = first + second;
    }

    def getOperationMode() : Int = {
        return ADD_OPERATION;
    }

    def getOperationName() : String = {
      return ADD_OPERATION_NAME;
    }

    override def toString() : String = {
      return first + " ＋ " + second + " = " + result;
    }
}
```

引き算

```scala:SubtractOperation.scala
class SubtractOperation extends FourOperation {

  var first = 0;
  var second = 0;
  var result = 0;

  def doOperation(first: Int, second: Int) {
    this.first = first;
    this.second = second;
    result = first - second;
  }

  def getOperationMode(): Int = {
    return SUBTRACT_OPERATION;
  }

  def getOperationName(): String = {
    return SUBTRACT_OPERATION_NAME;
  }

  override def toString(): String = {
    return first + " － " + second + " = " + result;
  }
}
```

掛け算

```scala:MultiplicationOperation.scala
class MultiplicationOperation extends FourOperation {

  var first = 0;
  var second = 0;
  var result = 0;

  def doOperation(first: Int, second: Int) {
    this.first = first;
    this.second = second;
    result = first * second;
  }

  def getOperationMode(): Int = {
    return MULTIPLICATION_OPERATION;
  }

  def getOperationName(): String = {
    return MULTIPLICATION_OPERATION_NAME;
  }

  override def toString(): String = {
    return first + " × " + second + " = " + result;
  }
}
```

割り算

```scala:DivisionOperation.scala
class DivisionOperation extends FourOperation {
  var first = 0;
  var second = 0;
  var result = 0;
  var odd = 0;

  def doOperation(first: Int, second: Int) {
    this.first = first;
    this.second = second;
    result = first / second;
    odd = first % second;
  }

  def getOperationMode(): Int = {
    return DIVISION_OPERATION;
  }

  def getOperationName(): String = {
    return DIVISION_OPERATION_NAME;
  }

  override def toString(): String = {
    var odd = "";
    if (this.odd != 0) {
      odd = " 余り " + this.odd;
    }
    return first + " ÷ " + second + " = " + result + odd;
  }
}
```

例外（独自例外作る意味なさそうな気もする・・・）

```scala:FourOperationException.scala
class FourOperationException(message: String = null, cause: Throwable = null) extends RuntimeException(message, cause) {
}
```

入力値に対応する演算クラスを生成する

```scala:FourOperationFactory.scala
object FourOperationFactory {

  def createOperation(operationMode : Int) : FourOperation = {

      if (operationMode == 1) {
          return new AddOperation();
      } else if (operationMode == 2) {
          return new SubtractOperation();
      } else if (operationMode == 3) {
          return new MultiplicationOperation();
      } else if (operationMode == 4) {
          return new DivisionOperation();
      } else {
          throw new FourOperationException("処理番号は１～４までを選択してください。");
      }
  }
}
```

実行クラス

```scala:FourOperationExecutor.scala
import java.io.BufferedReader
import java.io.InputStreamReader

object FourOperationExecutor {
  def main(args: Array[String]): Unit = {
    execute();
  }

  def execute() {
    // 演算処理を決めます。
    var operation = createOperation();
    // 1番目の値を取得します。
    println(operation.getOperationName() + "を始めます。１つ目の数字を入力してください。");
    var first = getCmdLineString();
    // 2番目の値を取得します。
    println("２つ目の数字を入力してください。");
    var second = getCmdLineString();
    // 計算します。
    operation.doOperation(first.toInt, second.toInt);
    println("計算結果：" + operation);
  }

  def createOperation(): FourOperation = {
    try {
      println("処理番号を入力してください");
      println("１．加算　２．減算　３．乗算　４．除算");
      val operationMode = getCmdLineString();
      validateOperationMode(operationMode);
      return FourOperationFactory.createOperation(operationMode.toInt);
    } catch {
      case e : FourOperationException => println(e.getMessage); createOperation();
    }
  }

  def getCmdLineString(): String = {
    val reader = new BufferedReader(new InputStreamReader(System.in));
    return reader.readLine();
  }

  def validateOperationMode(operationMode: String): Unit = {
    if (operationMode == null || operationMode.length() == 0) {
      throw new FourOperationException("処理番号は１～４までを選択してください。");
    }

    if (!operationMode.matches("[0-9]")) {
      throw new FourOperationException("処理番号は１～４までを選択してください。");
    }
  }
}
```

こんな感じなのか・・・？
入力チェックが適当、0除算考慮してないなど色々あるけどとりあえず普通の計算はでけた。
うーん、scala的にこんなんで問題無いのかどうかがようわからんのでもうちょい勉強せねば。