隐式解包当初始化期间无法定义的常量时可选,但错误来了

时间:2016-07-16 10:47:15

标签: swift initialization options

由Drewag回答the question

  

每个成员常量必须在初始化完成时具有值。有时,在初始化期间无法使用正确的值初始化常量,但仍可保证在访问之前具有值。

     

使用Optional变量可以解决这个问题,因为Optional会自动使用nil初始化,并且它最终包含的值仍然是不可变的。然而,不断展开一个你知道肯定不是零的变量可能会很痛苦。 Implicitly Unwrapped Optionals实现了与Optional相同的好处,并且具有额外的好处,即不必在任何地方明确地展开它。

以下代码定义了两个类CountryCity,每个类都将另一个类的实例存储为属性。每个国家都必须有一个首都,每个城市必须始终属于一个国家。

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!,编译器会发出以下错误警告。

enter image description here

问题:当初始化期间无法定义的常量时,我​​们可以使用Implicitly Unwrapped Optional吗?这里的错误是什么?如果我理解错了,我很感激你可以指出并帮助我。

1 个答案:

答案 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!