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] の意味が分かれば、オプショナルの理解がかなりできているんでしょうね。
私は当然分かりますよ。
ということで今日はここまで。