2016-06-16 3 views
0

Я нахожусь на второй лекции по курсу разработчика IOS 9 в Стэнфорде. Лектор пытается построить калькулятор. Я не могу понять две части. One:Почему эта переменная должна быть развернута?

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 
     } 
    } 
} 

ответ

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

почему это, что я до сих пор, чтобы заставить разворачивать его, когда я вложен его в «IF» заявление, которое проверяет, если она равна нулю или нет?

Свифт - это строго типизированный язык. В этом случае pending имеет тип PendingBinaryOperationInfo?. Просто потому, что вы проверили его, чтобы убедиться, что это не nil не меняет того факта, что pending имеет тип PendingBinaryOperationInfo?. Вам все равно нужно развернуть его, чтобы получить доступ к PendingBinaryOperationInfo, который завернут опцией.

Проверка на nil только гарантирует, что вы можете смело разворачивать pending с !, потому что теперь вы знаете, что это не будет работать из-за pending быть nil.

Иногда программисты пишут это так:

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

Это использует опционального связывание разворачивать pending и назначить его на новую переменную unwrappedPending, которая имеет типа PendingBinaryOperationInfo (который не необязательно) ,

Иногда, вы можете также увидеть это:

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, и у вас больше нет доступа к исходному дополнительному pending внутри if.


Вторая часть:

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

почему две переменные не должны иметь Инициализатора? это просто потому, что он находится под «структурой»»

Да Для структур, Swift автоматически генерирует инициализатор для Вас, который инициализирует все свойства Вы можете увидеть это инициализатор с автозаполнения функции Xcode, набрав:..

PendingBinaryOperationInfo(

Как только вы набираете ( инициализатор появится в предложенном завершении Здесь в Playground:.

autocompletion example in a Playground

+0

Спасибо, что нашли время, чтобы написать такой ясный ответ! –

+0

Добро пожаловать! – vacawama

0

Вы проверки nil, но объект не разворачивал, что вы можете сделать что-то вроде этого

if let pending = pending { ... } 

Вторая часть вашего вопроса, то переменные в этом struct являются НЕ nil поэтому при инициализации PendingBinaryOperationInfo вы должны инициализировать его с non-null значениями, вы можете обойти это путем присвоения значений по умолчанию в struct

0

Аккумулятор переменных не является необязательным и не может стать нулевым, поэтому вам необходимо принудительно развернуть ожидающий необязательный параметр и не может использовать необязательный вопросительный знак вопроса (?), Который может возвращать нуль.

Структура PendingBinaryOperationInfo не имеет значений по умолчанию и поэтому должна быть инициализирована.

Смежные вопросы