加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift学习笔记二

发布时间:2020-12-14 02:04:43 所属栏目:百科 来源:网络整理
导读:新建一个类,作为计算器的 Model 层,这里将类命名为 CalculatorBrain import Foundationclass CalculatorBrain { //1 private enum Op { case Operand(Double) case UnaryOperation(String,Double - Double) case BinaryOperation(String,(Double,Double) -

新建一个类,作为计算器的 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)
        
        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("÷",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 一节。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读