2016-07-20 2 views
5

Я пытаюсь понять, как работает ленивый. Следующий код компилируется без ошибок.Ошибка компиляции при использовании ленивой переменной

import UIKit 
class Test : UIViewController{ 
    let i = 1 
    lazy var j:Int = self.i 
} 

В то время как, если удалить тип J и сделать вывод, как приведенный ниже код,

import UIKit 
class Test : UIViewController{ 
    let i = 1 
    lazy var j = self.i 
} 

Я получаю ошибку компиляции «Значение типа 'NSObject ->() -> Test' имеет no member 'i' "

Может кто-нибудь объяснить, что происходит с компилятором. Спасибо

ответ

4

Вам нужно рассмотреть 3 аспекта здесь.

  • Ленивое хранимое имущество - это свойство, начальное значение которого не равно , рассчитанное до момента его первого использования. То есть, когда вы вызываете свойство в первый раз, его значение будет рассчитано.
  • Поскольку фактическое значение создается путем оценки, вам нужно объявить тип данных ленивой переменной вверх.
  • Свойства, которые вы объявляете в своем классе, являются переменными экземпляра, , если вам нужно получить доступ к их значениям, вам нужен экземпляр (объект) класса.

Рассмотрим следующую строку из вашего неработающего кода

lazy var j = self.i 

Две проблемы присутствуют в вашем неработающего кода. Во-первых, вы не указали тип данных вашего ленивого var. Поскольку объявление является неполным, компилятор не будет рассматривать «j» как ленивый var, который он будет рассматривать как обычную переменную экземпляра. Вы должны знать о правиле swift, что всякий раз, когда вы объявляете какую-либо переменную в классе, вы должны присвоить ей какое-то значение, иначе вы можете сделать эту переменную опциональной. В приведенном выше заявлении вы пытаетесь присвоить значение i j, используя self внутри класса. Когда компилятор компилирует эту строку, объект класса не создается, а сам, который вы используете, равен нулю, поэтому компилятор бросает ошибку (он будет вызывать ошибку, даже если вы не используете self по той же причине, о которой говорилось выше) ,

Почему это не вызывает проблемы в рабочем коде:

lazy var j:Int = self.i 

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

Короче две вещей, которые вы должны понимать, 3 вещей

  • Заявляя ленивый вар вы должны указать тип данных
  • ленивого вара не назначаются, когда она объявляется, она назначается, когда его называется
  • вы не можете вызвать экземпляр вар без экземпляра (объекта) вашего класса
+0

Я не думаю, что тип данных требуется при объявлении ленивого вара. Код 'lazy var name =" some name "' компилируется без каких-либо проблем –

+2

Если вы передаете какое-либо жестко заданное значение в lazy var, не требуется тип данных, то компилятор поймет тип, поэтому lazy var name = "some name" работает. В вашем коде вы не назначаете значение напрямую, вы пытаетесь присвоить значение i с помощью self. Здесь компилятор не знает о себе, типе данных i и i. Вот почему тип данных требуется в таких случаях, а также в случае, когда вы пишете закрытие вашего ленивого var. –

0

Вот пример отложенной инициализации с контролем зрения Лер

Обратите внимание на() в конце

lazy var myViewController : MyViewController? = { 
    let storyboard: UIStoryboard = UIStoryboard(name: "MyVC", bundle: nil) 
    return storyboard.instantiateViewController(withIdentifier: "MyAccount") as? MyViewController 
}() 
Смежные вопросы