2017-02-01 8 views
1
func runningMetersWithMetersPerDay (metersPerDay: Int) ->() -> 
Int { 
    var totalMeters = 0 
    return { 
     totalMeters += metersPerDay 
     return totalMeters 
    } 
} 
var planA = runningMetersWithMetersPerDay (metersPerDay: 2000) 
planA() 
planA() 

Первый planA() печати 2000 и второй planA() печати 4000. количество накапливается каждый раз, когда я называю planA() Почему? В этой функции используется var totalMeters = 0? Есть planA() так же, как runningMetersWith MetersPerDay (metersPerDay: 2000)? Если нет, какая разница между ними? Спасибо за помощь.Небольшой вопрос о функции и закрытия

ответ

1

Ну, ваш метод возвращает закрытие, которое вы удваиваете дважды. Закрытие захватывает Это окружающая среда, в вашем случае «внешняя» переменная totalMeters и сохраняет ее за счет различных вызовов.

Если это не то, что вы хотите, вы должны положить totalMeters в крышку, как это:

func runningMetersWithMetersPerDay (metersPerDay: Int) ->() -> 
Int { 
    return { 
     var totalMeters = 0 
     totalMeters += metersPerDay 
     return totalMeters 
    } 
} 

Чтобы ответить на этот вопрос с комментарием ниже: Я модифицировал оригинальные функции и вызовы, чтобы распечатать некоторые намеков:

func runningMetersWithMetersPerDay (metersPerDay: Int) ->() -> 
    Int { 
     print ("rMWMD called") 
     var totalMeters = 0 
     return { 
      totalMeters += metersPerDay 
      print ("calculated new result: \(totalMeters)") 
      return totalMeters 
     } 
} 

print ("start") 
var planA = runningMetersWithMetersPerDay (metersPerDay: 2000) // "rMWMPD called" 
print ("got planA") 
planA() // "calculated new result:2000" 
planA() // "calculated new result:4000" 

runningMetersWithMetersPerDay (metersPerDay: 2000)() // "calculated new result: 2000" 
planA() // "calculated new result:6000" 
print ("end") 

planA является повторным (замыкание типа (())->Int - введите void параметров и возврата Int), и затем вы затем дважды запустите замыкание и получите результаты (2000, 4000).

Теперь функция runningMetersWithMetersPerDay(metersPerDay:) вызывается снова возвращает новый закрытия и это возвращаемое значение, то та или иная строчка. Он возвращает 2000, так как это новое закрытие (хотя и не назначено переменной). Думай о нем, как следующее:

runningMetersWithMetersPerDay (metersPerDay: 2000) /* "rMWMPD called" and now call the closure: */() // "calculated new result: 2000" 

В конце концов вы выполнить PLANA в третий раз, и так как он все еще держит его собственное состояние (например, собственное totalMeters значение), она возвращает 6000.

+0

Привет, спасибо за ваш ответ. Но я нахожу еще один маленький вопрос. Сначала я дважды вызывал planA(), и результат печатал 2000 и 4000, затем я попытался вызвать runMetersWithMetersPerDay (metersPerDay: 2000)(), а результат печатает 2000, затем я снова вызвал planA(), результат печатает 6000. Теперь planA = runningMetersWithMetersPerDay (metersPerDay: 2000), почему это так отличается, когда я вызывал planA() и runningMetersWithMetersPerDay (metersPerDay: 2000)()? – Wilson

+0

@Wilson: Пожалуйста, посмотрите на мой измененный ответ, надеюсь, что теперь это станет ясно. –

0

Что происходит здесь нормально. Пошли шаг за шагом.

Во-первых, вы бежите:

var planA = runningMetersWithMetersPerDay (metersPerDay: 2000) 

Что вы выполняете здесь?

var totalMeters = 0 
return { 
    totalMeters += metersPerDay 
    return totalMeters 
} 

Что у вас есть в плане?

  1. контекст с переменной totalMeters
  2. fonction готов к выполнению в этом контексте

Первый запуск, totalMeters = 0

{ 
    totalMeters += metersPerDay 
    return totalMeters 
}() 

Второй пробег, totalMeters = 2000

{ 
    totalMeters += metersPerDay 
    return totalMeters 
}() 

новый результат = 4000

+1

Привет, спасибо за ваш ответ. – Wilson

+0

Кинда ответил в то же время, что и Андреас :) ха-ха! Добро пожаловать в Уилсон. – Mikael