Разница между вычисляемым свойством и набором свойств с закрытием

Я новичок в Swift. В чем разница между вычисляемым свойством и свойством, установленным на закрытие? Я знаю, что вычисляемое свойство каждый раз пересчитывается. По закрытию он другой? т.е.

Закрытие:

var pushBehavior: UIPushBehavior = {
    let lazilyCreatedPush = UIPushBehavior()
    lazilyCreatedPush.setAngle(50, magnitude: 50)
    return lazilyCreatedPush
}()

Рассчитано

var pushBehavior: UIPushBehavior {
    get{
        let lazilyCreatedPush = UIPushBehavior()
        lazilyCreatedPush.setAngle(50, magnitude: 50)
        return lazilyCreatedPush
    }
}

person bakalolo    schedule 20.07.2015    source источник


Ответы (4)


Короче говоря, первое - это сохраненное свойство, которое инициализируется посредством замыкания, причем это замыкание вызывается только один раз, когда оно инициализируется. Второе - это вычисляемое свойство, блок get которого вызывается каждый раз, когда вы ссылаетесь на это свойство.


Закрытие инициализации сохраненного свойства вызывается один раз и только один раз, но позже вы можете изменить значение сохраненного свойства (если вы не замените var на let). Это полезно, когда вы хотите инкапсулировать код для инициализации сохраненного свойства в одном кратком блоке кода.

Однако блок вычисляемого свойства вызывается каждый раз, когда вы ссылаетесь на переменную. Это полезно, когда вы хотите, чтобы код вызывался каждый раз, когда вы ссылаетесь на вычисляемое свойство. Обычно вы делаете это, когда вычисляемое свойство необходимо пересчитывать каждый раз, когда вы ссылаетесь на сохраненное свойство (например, пересчитывается из других, возможно частных, сохраненных свойств).

В этом случае вам, несомненно, понадобится сохраненное свойство (первый пример), а не вычисленное свойство (второй пример). По-видимому, вам не нужен новый объект поведения push каждый раз, когда вы ссылаетесь на переменную.


Между прочим, в вашем первом примере вы внутренне ссылаетесь на его ленивое создание. Если вы хотите такого поведения, вы должны использовать ключевое слово lazy:

lazy var pushBehavior: UIPushBehavior = {
    let behavior = UIPushBehavior()
    behavior.setAngle(50, magnitude: 50)
    return behavior
}()

Однако, если свойство равно static, оно автоматически создается лениво.

person Rob    schedule 20.07.2015
comment
Замечательное объяснение .. !! ;) - person itsji10dra; 07.03.2017

Закрытие:

  //closure
    var pushBehavior: UIPushBehavior = {
        let lazilyCreatedPush = UIPushBehavior()
        lazilyCreatedPush.setAngle(50, magnitude: 50)
        return lazilyCreatedPush
    }()

В первый раз, когда вызывается переменная pushBehavior, выполняется выполнение блока, и значение сохраняется в переменной pushBehavior. после этого всякий раз, когда вы вызываете pushBehavior, это значение возвращается.

означает, что в этой переменной выполняется и сохраняется только первый блочный код. Кроме того, вы можете хранить значение переменной, когда захотите, но после этого это значение будет возвращено, но если вы объявите как let, вы не сможете изменить это значение.

Вычисляемое свойство:

var pushBehavior: UIPushBehavior {
    get{
        let lazilyCreatedPush = UIPushBehavior()
        lazilyCreatedPush.setAngle(50, magnitude: 50)
        return lazilyCreatedPush
    }
}

В вычисляемом свойстве всякий раз, когда вы вызываете переменную pushBehavior, этот блок выполняется и возвращается значение. поэтому каждый раз, когда выполняется блок. и вы не можете объявить переменную как ключевое слово let для переменной pushBehavior.

Таким образом, вы можете использовать этот код в соответствии с вашими требованиями.

person vikas prajapati    schedule 23.11.2016
comment
Замыкающий будет инициализирован немедленно, независимо от того, используете вы его или нет. Это не ленивая инициализация. Кстати, пишите первое слово после точки с большой буквы, это сделает чтение немного более приятным. - person Kent Liau; 27.12.2016

Основное отличие состоит в том, что вы не можете назначить что-либо вычисляемому свойству, поскольку у него нет установщика. В этом случае замыкание вызывается только один раз, а возвращаемое значение сохраняется в переменной, поэтому, если результат не меняется с течением времени, более эффективно использовать сохраненную переменную, а не вычисленную.

В общем: вычисляемые свойства следует использовать только в том случае, если значение можно получить быстро.

Примечание: если вы не изменяете / не переназначаете сохраненную переменную, вам следует подумать о том, чтобы сделать ее константой (let)

person Qbyte    schedule 20.07.2015

Это не ответ, но об этом стоит упомянуть:

  • В сохраненных свойствах значение должно быть известно после инициализации. Это происходит либо по умолчанию, либо при инициализации.
  • Значение вычисляемого свойства не вычисляется до тех пор, пока к нему не будет получен доступ.
  • Значение свойства с отложенной загрузкой не определяется до тех пор, пока к нему не будет получен доступ

следовательно, как для вычисляемых, так и для отложенных переменных вы можете без проблем получить доступ к self или сохраненным свойствам.

person Honey    schedule 13.06.2018
comment
Для ленивых переменных: не определен до тех пор, пока он не будет доступен, может быть переписан, поскольку не вычисляется до тех пор, пока он не будет доступен, но я чувствую, что есть тонкая разница в значении для определения против вычислений ... - person Honey; 23.10.2020