我正在学习learn-swift playground并在学习语言时将其升级到Swift 2.0。下面的代码(可能与之前版本的Swift一起使用)现在产生两个错误:“在初始化所有存储属性之前使用'self'”和在初始化之前使用“Constant'self.capitalCity”
class Country
{
let name: String
let capitalCity: City!
init(name: String, capitalName: String)
{
self.name = name
self.capitalCity = City(name: capitalName, country: self)
}
}
class City
{
let name: String
unowned let country: Country
init(name: String, country: Country)
{
self.name = name
self.country = country
}
}
阅读answer to a similar question我发现我可以将let capitalCity: City!
更改为var capitalCity: City!
并解决语法错误。
我意识到,在这个人为的例子中,一个国家的首都可以改变,所以这样会很好,但如果有一个价值确实是一个常数的情况怎么办呢?
有什么方法可以解决语法错误,同时保持capitalCity不变?
答案 0 :(得分:16)
在这种情况下,我建议你通过计算属性使属性成为变量但隐藏它(使它看起来像一个常量):
class Country {
let name: String
private var _capitalCity: City!
var capitalCity: City {
return _capitalCity
}
init(name: String, capitalName: String) {
self.name = name
self._capitalCity = City(name: capitalName, country: self)
}
}
答案 1 :(得分:12)
有什么方法可以解决语法错误,同时保持
capitalCity
不变?
不是你设置的方式。问题的根源实际上是,为了设置capitalCity
,您必须创建country
为self
的城市。 那是编译器反对的self
的使用:
self.capitalCity = City(name: capitalName, country: self)
^^^^
由于您已将城市的country
配置为常量,因此在初始化城市时,必须提供此值。因此你没有出路;您必须使capitalCity
成为可选var
,以便它具有合法的其他初始值,即nil
。您提出的解决方案实际上是这样的:
class Country
{
let name: String
var capitalCity: City! = nil // implicit or explicit
init(name: String, capitalName: String)
{
self.name = name
// end of initialization!
// name is set (to name), and capitalCity is set (to nil)...
// ... and so the compiler is satisfied;
// now, we _change_ capitalCity from nil to an actual City,
// and in doing that, we _are_ allowed to mention `self`
self.capitalCity = City(name: capitalName, country: self)
}
}
答案 2 :(得分:0)
只需:
private(set) var capitalCity: City!
为您提供所需的只读公共接口。
我了解到您发现var capitalCity: City!
人为。我会说the selected answer确实是人为的;它添加了除了解决与语言有关的问题外没有其他用途的代码行。这样的行是毫无意义的,而意义是代码中内容最重要的部分。