Swiftで遊ぼう! on Hatena

あしたさぬきblogでやってた初心者オヤジのiOSプログラミング奮闘記がHatenaに来ました

Swiftで遊ぼう! - 217 - Developing iOS 8 Apps with Swift - Applying MVC Enumration

Swiftで遊ぼう!の古い記事-> Life-LOG OtherSide

計算機のViewに並べられたボタンには複数の機能が割りふられている。

これを実現するためにもってこいの機能がイーナムだ。複数の選択肢から1つのオプションを選択できる。

じゃあ真っ新なCalculatorBrain.swiftファイルにクラスを設計していこう。

import Foundationの下に次のコードを書く

class CalculatorBrain {

}

これがクラスの骨格で、継承するスーパークラスを持たない自分で作る新規のクラスに機能を割りふるイーナムプロパティを持たせる。

このプロパティ名をOpとする。

class CalculatorBrain {
 enum Op {
  case Operand
  case UnaryOperation
  case BinaryOperation
 }
}

すっかりイーナムの宣言法を忘れてしまっているので復習(^_^;)

これはイーナムの基本宣言であるが、これだけじゃまだ不十分です。イーナムのいいところは、caseを使ってどれか1つ選択肢を選べるということ。

当然これだけでイーナム宣言ができているわけではない。重要なのはそれぞれのcaseにAssociation Valueを持つことだ。

enum Op {
 case Operand(Double)
 case UnaryOperation(String, Double -> Double)
 case BinaryOperation(String, (Double, Double) -> Double)
}

OpがOperandだったら、Double型のアソシエーションバリューを持つけど、UnaryOperationだったら、String型とクロージャ(関数)を受け取る関数、BinaryOpertionは2つの引数を受けとって返すクロージャを処理する関数で挙動がかなり異なる。

挙動が異なっても、これはイーナム型の変数という共通点でくくれるため、アレー型変数を用意してスタック管理できるようになる。素晴らしい考え方だ!

Operand(数字ボタンでも関数ボタンでもすべて)を集めたアレーは次のように宣言して、単純な数字のみの情報はpushOperand関数で積み上げていく。

var opStack = [Op]()

func pushOperand(operand: Double) {
 opStack.append(Op.Operand(operand))
}

それからString型と関数の組み合わせの関係をディクショナリ型で表現する。

var knownOps = [String: Op]()

func performOperation(symbol: String) {
// not yet coding
}

これで準備ができたので、CalculationBrainクラスのインスタンス化に必要なイニシャライザを実装しよう。

knownOpsは、初期化する時に実装されるべきディクショナリ型変数なので、計算機にある関数ボタンを持たせよう。

ということで、ここまでをコーディングすると

class CalculatorBrain {
 
 enum Op {
  case Operand(Double)
  case UnaryOperation(String, Double -> Double)
  case BinaryOperation(String, (Double, Double) -> Double)
 }
    
 var opStack = [Op]()
    
 var knownOps = [String: Op]()
    
 init() {
  knownOps["×"] = Op.BinaryOperation("×") {$0 * $1}
  knownOps["÷"] = Op.BinaryOperation("÷") {$1 / $0}
  knownOps["+"] = Op.BinaryOperation("+") {$0 + $1}
  knownOps["−"] = Op.BinaryOperation("−") {$1 - $0}
  knownOps["√"] = Op.UnaryOperation("√", sqrt)
 }
    
 func pushOperand(operand: Double) {
  opStack.append(Op.Operand(operand))
 }
    
 func performOperation(symbol: String) {
  if let operation = knownOps[symbol] {
   opStack.append(operation)
  }
 }
}

最後のperformOperation関数の if let operation = knownOps[symbol] の意味が分かれば、オプショナルの理解がかなりできているんでしょうね。

私は当然分かりますよ。

ということで今日はここまで。