由Drewag回答the question
每个成员常量必须在初始化完成时具有值。有时,在初始化期间无法使用正确的值初始化常量,但仍可保证在访问之前具有值。
使用Optional变量可以解决这个问题,因为Optional会自动使用nil初始化,并且它最终包含的值仍然是不可变的。然而,不断展开一个你知道肯定不是零的变量可能会很痛苦。 Implicitly Unwrapped Optionals实现了与Optional相同的好处,并且具有额外的好处,即不必在任何地方明确地展开它。
以下代码定义了两个类Country
和City
,每个类都将另一个类的实例存储为属性。每个国家都必须有一个首都,每个城市必须始终属于一个国家。
class Country {
let name: String
var capitalCity: City! //why I can't use let!
init(name: String, capitalName: String){
self.name = name
self.capitalCity = City(name: capitalName, country: self)
}
deinit {
print("\(name) has been de-initialized the city \(capitalCity.name) is gone with with the country")
}
}
class City{
let name: String
unowned let country: Country
init(name: String, country: Country){
self.name = name
self.country = country
}
deinit {
print("The city \(name) has been de-initialized ")
}
}
var country = Country(name: "Canada", capitalName: "Ottawa")
}
但是,如果我将行var capitalCity: City!
更改为let capitalCity: City!
,编译器会发出以下错误警告。
问题:当初始化期间无法定义的常量时,我们可以使用Implicitly Unwrapped Optional吗?这里的错误是什么?如果我理解错了,我很感激你可以指出并帮助我。
答案 0 :(得分:1)
重要的部分在这里:
City(name: capitalName, country: self)
您肯定在分配给属性self
之前执行的表达式中使用capitalCity
。
如果要在任何表达式中使用self
,则需要处于two phase initialization的第二阶段,这意味着在使用self
之前需要初始化所有属性}。
使用var
时,Swift会为属性nil
分配默认初始值capitalCity
。因此,可以将该属性视为“已初始化”,因此,您可以在初始化另一个属性self
后使用name
。
(你知道将nil
赋予ImplicitlyUnwrappedOptional
的let-constant是荒谬的。)
顺便说一下private(set) var
经常用于类似情况:
private(set) var capitalCity: City!