swift学习笔记二

新建一个类,作为计算器的 Model 层,这里将类命名为 CalculatorBrain

import Foundation

class CalculatorBrain {
    //1
    private enum Op {
        case Operand(Double)
        case UnaryOperation(String, Double -> Double)
        case BinaryOperation(String, (Double, Double) -> Double)
    }
    
    //2
    private var opStack = [Op]()
    
    private var knownOps = [String:Op]()
    
    //3
    init() {
        knownOps["×"] = Op.BinaryOperation("×", *)
        knownOps["÷"] = Op.BinaryOperation("÷", { $1 / $0 })
        knownOps["+"] = Op.BinaryOperation("+", +)
        knownOps["−"] = Op.BinaryOperation("−", { $1 - $0 })
        knownOps["√"] = Op.UnaryOperation("√", sqrt)
    }
    
    //4
    func evaluate(ops: [Op]) -> (result: Double?, remainOps: [Op])
    {
        if !ops .isEmpty {
            let op = ops.removeLast() // error : Immutable value of type '[CalculatorBrain.Op]' only has mutating members named 'removeLast'
        }
        
        return (nil, ops)
    }
    
    //6
    func pushOperand(operand: Double) {
        opStack.append(Op.Operand(operand))
    }
    
    //7
    func performOperation(symbol: String) {
        if let operation = knownOps[symbol] {
            opStack.append(operation)
        }
    }
}
东西很多,一点一点消化吧,

//1 

定义了一个私有的 enum,一般在 object - C 里面我们是这样定义枚举的

typedef NS_ENUM(NSUInteger, HTTPMethod) {
    HTTPMethodGet,
    HTTPMethodPost,
};
但是这里的枚举值却是函数,很奇怪,这个还得去查资料了解一下,先放着.........

//2

声明了一个数组 opStack 和一个字典 knownOps 并初始化。


//3

函数的初始化,为 knownOps 字典赋值,这里比较有趣,BinaryOperation 在定义需要的参数是一个 String 和函数(这个函数需要 2 个 Double 类型的参数,返回值是 Double 类型), 而在初始化时这样写  knownOps["÷"] = Op.BinaryOperation("÷", { $1 / $0 })  并不奇怪,swift 学习笔记1 里面已经说过了,有趣的是这里的闭包竟然可以直接省略成 * 和 + 就可以代表 (Double, Double) -> Double 了。这是因为在 swift 里所有的操作符都是符号,* 其实就是代表 { $0 * $1 } 了,+ 代表 { $0 + $1 } ,所以可以直接省略写成 * 和 + ,至于 ÷ 和 − 后面的闭包 { $1 / $0 } 和 { $1 - $0 } 不能省略成 ÷ 和 − ,因为运算方向是相反的。


//4

有两个知识点

1)函数返回的是一个元组(Tuple) 

2)这里的 let op = ops.removeLast() 会报错,因为 ops 是一个不可变变量。为什么是一个不可变变量呢?swift 里规定,传过来的参数,除了类之外其他的都是值拷贝,类为引用。数组和字典都是结构体,所以是值拷贝,这点需要牢记。

当然,你可以这样修改:

var remainingOps = ops;
let op = remainingOps.removeLast()



--------------------分割线-------------------


完整的 CalculatorBrain 代码如下:

//
//  CalculatorBrain.swift
//  Calculator
//
//  Created by aaron.zheng on 2015-06-27.
//  Copyright © 2015 aaron.zheng. All rights reserved.
//

import Foundation

class CalculatorBrain {
    //1
    private enum Op: CustomStringConvertible {
        case Operand(Double)
        case UnaryOperation(String, Double -> Double)
        case BinaryOperation(String, (Double, Double) -> Double)
        
        var description: String { //要实现自己的 description 就得让 enum 实现 CustomStringConvertible 协议。
            get {
                switch self {
                case .Operand(let operand):
                    return "\(operand)"
                case .UnaryOperation(let symbol, _):
                    return symbol
                case .BinaryOperation(let symbol, _):
                    return symbol
                }
            }
        }
    }
    
    //2
    private var opStack = [Op]()
    
    private var knownOps = [String:Op]()
    
    //3
    init() {
        func learnOp(op: Op) {
            knownOps[op.description] = op
        }
        learnOp(Op.BinaryOperation("×", *)) //下面的同样可以换成用 learnOp。
        knownOps["÷"] = Op.BinaryOperation("÷", { $1 / $0 })
        knownOps["+"] = Op.BinaryOperation("+", +)
        knownOps["−"] = Op.BinaryOperation("−", { $1 - $0 })
        knownOps["√"] = Op.UnaryOperation("√", sqrt)
    }
    
    //4
    private func evaluate(ops: [Op]) -> (result: Double?, remainOps: [Op])
    {
        if !ops .isEmpty {
            var remainingOps = ops;
            let op = remainingOps.removeLast()
            switch op {
            case .Operand(let operand):
                return (operand, remainingOps)
            case .UnaryOperation(_, let operation):
                let operandEvaluation = evaluate(remainingOps)
                if let operand = operandEvaluation.result {
                    return (operation(operand), operandEvaluation.remainOps)
                }
            case .BinaryOperation(_, let operation):
                let op1Evaluation = evaluate(remainingOps)
                if let operand1 = op1Evaluation.result {
                    let op2Evaluation = evaluate(op1Evaluation.remainOps)
                    if let operand2 = op2Evaluation.result {
                        return (operation(operand1,operand2),op2Evaluation.remainOps)
                    }
                }
                
            }
        }
        
        return (nil, ops)
    }
    
    //5
    func evaluate() -> Double? {
        let (result, _) = evaluate(opStack) //_ 起占位作用,表示我不关心该参数。
        return result
    }
    
    //6
    func pushOperand(operand: Double) -> Double? {
        opStack.append(Op.Operand(operand))
        return evaluate()
    }
    
    //7
    func performOperation(symbol: String) -> Double? {
        if let operation = knownOps[symbol] {
            opStack.append(operation)
        }
        return evaluate()
    }
}


更多可以看《Developing IOS 8 App With Swift》的 Applying MVC 一节。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值