"Если функции по сути являются замыканиями." Это не правда Функции (и методы) - это не то же самое, что замыкания. Функции имеют все свои свободные переменные без привязки. Замыкания связывают некоторые или все свои свободные переменные (закрытые над ними, отсюда и название "замыкание").
«Свободная переменная» - это любая переменная, определенная вне области действия функции (включая ее формальные параметры). Функция верхнего уровня func f(x: Int)
имеет одну свободную переменную; когда вы вызываете его, вы должны передать параметр. Закрытие типа { f(1) }
не имеет свободных переменных. Когда вы вызываете его, вы не передаете никаких параметров.
Метод, как и функция, ничего не захватывает. Он передается всем своим свободным переменным, когда он выполняется. Например, когда вы делаете вызов object.doThis()
, это то же самое, что и вызов Type.doThis(object)()
.
class X {
func doThis() {}
}
let x = X()
x.doThis()
X.doThis(x)() // Same thing
X.doThis(x)
- это функция, которая возвращает функцию. Здесь нет магии. Все свободные переменные предоставляются во время разговора. Ничего не захвачено. («Свободная переменная» в описываемом вами случае - self
, но это ничего не меняет. self
не является чем-то особенным, за исключением того, что вокруг него появляется немного синтаксического сахара.)
Это отличается от замыкания:
let c = { x.doThis() }
c()
Когда я звоню c()
, как он узнает значение x
? Возможно, я вернул c
, а x
может быть вне зоны видимости. Система должна отслеживать x
(в том числе делать сильную ссылку, чтобы она не освобождалась), и она делает это, захватывая ее или «замыкаясь по x», что повышает вероятность сохранения циклов. Так что в c
, x
связано. Это не бесплатно. Вы не можете передать его, когда позвоните c()
.
self
здесь не является особенным. Это просто другая переменная. [weak self]
в замыканиях тоже не особенное. Вы также можете написать [weak x]
. Синтаксис [...]
- это просто список захвата.