为什么这个变量必须打开?

时间:2016-06-16 16:00:49

标签: swift structure optional

我参加了斯坦福大学IOS 9开发者课程的第二讲。讲师正试图建立一个计算器。我无法弄清楚两个部分。 之一:

if pending != nil {
            accumulator = pending!.binaryFunction(pending!.firstOperand, accumulator)
            pending = nil

我知道待处理是可选的。但是为什么当我把它嵌套在" IF"中时,我仍然必须强行打开它。检查是否为零的陈述?

第二部分是:

  private struct PendingBinaryOperationInfo {
        var binaryFunction: (Double, Double) -> Double
        var firstOperand: Double
    }

为什么这两个变量不需要初始化器?是因为它在"结构"?

之下

整个代码如下。我不理解的两个部分位于块的底部。

非常感谢!

import Foundation

class CalculatorBrain
{
    private var accumulator = 0.0

    func setOperand(operand: Double) {
        accumulator = operand
    }

    private var operations: Dictionary<String,Operation> = [
        "e" : Operation.Constant(M_E),
        "√" : Operation.UnaryOperation(sqrt),
        "cos" : Operation.UnaryOperation(cos),
        "×" : Operation.BinaryOperation({ $0 * $1 }),
        "÷" : Operation.BinaryOperation({ $0 / $1 }),
        "+" : Operation.BinaryOperation({ $0 + $1 }),
        "−" : Operation.BinaryOperation({ $0 - $1 }),
        "=" : Operation.Equals
    ]

    private enum Operation {
        case Constant(Double)
        case UnaryOperation ((Double) -> Double)
        case BinaryOperation ((Double, Double) -> Double)
        case Equals
    }

    func performOperation(symbol: String) {
        if let operation = operations[symbol] {
            switch operation {
            case .Constant(let value):
                accumulator = value
            case .UnaryOperation(let function):
                accumulator = function(accumulator)
            case .BinaryOperation(let function):
                executePendingBinaryOperation()
                pending = PendingBinaryOperationInfo(binaryFunction: function, firstOperand: accumulator)
            case .Equals:
                executePendingBinaryOperation()
            }
        }
    }

    private func executePendingBinaryOperation()
    {
        if pending != nil {
            accumulator = pending!.binaryFunction(pending!.firstOperand, accumulator)
            pending = nil
        }
    }

    private var pending: PendingBinaryOperationInfo?

    private struct PendingBinaryOperationInfo {
        var binaryFunction: (Double, Double) -> Double
        var firstOperand: Double
    }

    var result: Double {
        get {
            return accumulator
        }
    }
}

3 个答案:

答案 0 :(得分:1)

if pending != nil {
            accumulator = pending!.binaryFunction(pending!.firstOperand, accumulator)
            pending = nil
     

为什么当我将它嵌套在一个时,我仍然必须强行打开它   “IF”声明检查它是否为零?

Swift是一种强类型语言。在这种情况下,pending的类型为PendingBinaryOperationInfo?。仅仅因为您选中它以确保它不是nil并不会改变pending类型为PendingBinaryOperationInfo?的事实。您仍然需要打开它以访问由Optional包含的PendingBinaryOperationInfo

nil的检查只是确保您可以安全地将pending!解包,因为您现在知道它不会因pending nil而崩溃}。

有时,程序员会这样写:

if let unwrappedPending = pending {
    accumulator = unwrappedPending.binaryFunction(unwrappedPending.firstOperand, accumulator)
    pending = nil

这使用可选绑定来展开pending并将其分配给unwrappedPending类型的新变量PendingBinaryOperationInfo不< / em>可选)。

有时,您可能也会看到:

if let pending = pending {
    accumulator = pending.binaryFunction(pending.firstOperand, accumulator)
    pending = nil  // Oh, but this won't work because pending isn't optional

在这种情况下,会创建一个类型为pending的新变量PendingBinaryOperationInfo,它会隐藏原始pending变量。我个人不喜欢这种形式,因为它将问题与两个具有相同名称的不同类型的两个不同变量混淆。在这种情况下,它无论如何都不会起作用,因为作者还希望将pending设置为nil,并且您无法再访问{{1}内的原始可选pending }}

  

第二部分是:

if
     

为什么这两个变量不需要初始化器?是因为它处于“结构”之下?“

是。对于结构,Swift会自动为您生成初始化程序,以初始化所有属性。您可以通过键入以下内容来使用Xcode的自动填充功能查看此初始化程序:

private struct PendingBinaryOperationInfo {
    var binaryFunction: (Double, Double) -> Double
    var firstOperand: Double
}

只要您输入PendingBinaryOperationInfo( ,初始化程序就会弹出建议的完成时间。这是一个游乐场:

autocompletion example in a Playground

答案 1 :(得分:0)

您正在检查nil,但对象尚未解开,您可以做的就是这样

if let pending = pending { ... }

问题的第二部分,struct中的变量不是nil因此,当您初始化PendingBinaryOperationInfo时,必须使用non-null值初始化它,您可以通过在struct

中指定默认值来解决这个问题

答案 2 :(得分:0)

变量累加器不是可选的,不能变为nil,这就是为什么你必须强制解包挂起的可选项而不能使用可能返回nil的可选链接问号(?)的原因。

结构PendingBinaryOperationInfo没有默认值,因此必须初始化。