見出し画像

Swiftで行こう!--スタンフォードで電卓!5 MVC-2

ポール先生のMVCの講義も最後の仕上げです。

新しく作ったファイル、calcuratorBrain.swift、struct CalcuratorBrainを仕上げていきます。ここでは"+","-","="など必要な算術式も加えています。

計算機能のみ新しく作ったファイルに書いていきます。前回ではとりあえずファイルを変えても同じように表示されるかをやってうまくいきました。

次は実際に効率よく、Swiftの機能を使いながらコードを組んで行きます。

ポイントをまとめておきます。まずEnumeration Syntaxということで、

  private enum Operation{
       case constant(Double)
       case unaryOperation((Double)->Double)
       case binaryOperation((Double,Double)->Double)
       case equals
   }

enumのAssociated Value(関連型、付属型)を使う実装です。(Double)->Doubleは関数を意味しています。

binaryOperationはAssociated Valueに(Double,Double)->Doubleを持ちます。ここも2つの引数を持つ関数ですね。

次に今作ったenumを使ってDictionary,辞書を作ってひとまとめにしておきます。

 private var operations:Dictionary<String,Operation> = [
   
       "π": Operation.constant(Double.pi),
       "e":Operation.constant(M_E),
       "√":Operation.unaryOperation(sqrt),
       "cos":Operation.unaryOperation(cos),
       "±":Operation.unaryOperation({-$0}),
       "×":Operation.binaryOperation({$0 * $1}),
       "÷":Operation.binaryOperation({$0 / $1}),
       "+":Operation.binaryOperation({$0 + $1}),
       "-":Operation.binaryOperation({$0 - $1}),
       "=":Operation.equals
   
   ]

unaryOperationはAssociated Valueで関数を持ちますので"sqrt","cos"などが入っています。binaryOperationでは関数をClosureを使って簡潔に書いてあります。

もう一つenumを利用した関数を作ります。ここでは実際にaccumulatorに値を入れていきます。あと、"="、.equalsの挙動についても書いていきます。

mutating func performOperation(_ symbol:String){
       if let operation = operations[symbol]{
           switch operation{
           case .constant(let value):
               accumulator = value
           case .unaryOperation(let function):
               if accumulator != nil{
                   accumulator = function(accumulator!)
               }
           case .binaryOperation(let function):
               if accumulator != nil{
                   pbo = PendingBinaryOperation(function: function, firstOperand: accumulator!)
                   accumulator = nil
               }
           case .equals:
              performPendingBinaryOperation()
           }
       }
   }

そして、関数であればすぐに値が出てくるのですが、"a + b"のような場合、2つの数字で計算する時の処理をする命令、関数です。

"PendingBinaryOperation"として構造体で定義しています。

"="の関数については

private mutating func performPendingBinaryOperation()で定義しています。

    private mutating func performPendingBinaryOperation(){
       if pbo != nil && accumulator != nil{
           accumulator = pbo!.perform(with: accumulator!)
       }
   }
   
   private var pbo:PendingBinaryOperation?
   
   private struct PendingBinaryOperation{
       let function:(Double,Double) ->Double
       let firstOperand:Double
       func perform(with secondOperand:Double)->Double{
           return function(firstOperand,secondOperand)
       }
   }

最後にデータをViewControllerに渡す変数に入れていきます。

 mutating func setOperand(_ operand:Double){
       accumulator = operand
   }
   
   var result:Double?{
       get{
           return accumulator
       }
   }

のように、変数reaultに最終のデータが追加されます。

シュミレータでRUNしてみます。


いいなと思ったら応援しよう!