让我们说我在Swift中有以下类(有明显的问题)
class MyClass {
let myProperty: String
init() {
super.init()
self.setupMyProperty()
}
func setupMyProperty() {
myProperty = "x"
}
}
这过于简化,但我基本上试图将myProperty
的初始化委托给setupMyProperty()
方法。这是我经常用来打破课堂设置不同部分的模式。
但是,当然,在超级初始化程序运行之前我无法调用self
,并且我无法运行超级初始值设定项,直到所有属性都已设置为止,因此我可以使用超级初始化程序。最后,由于setupMyProperty()
不被视为初始化程序,因此无论如何都无法指定myProperty
。
有谁能告诉我如何在Swift中实现这种模式?
答案 0 :(得分:37)
将其声明为隐式解包的可选
class MyClass : NSObject {
var myProperty: String!
init() {
super.init()
self.setupMyProperty()
}
func setupMyProperty() {
self.myProperty = "x"
}
}
第499页" Swift编程语言"手册
答案 1 :(得分:9)
setupMyProperty
是否需要访问自己?如果没有,您可以使用类方法实现此目的:
class MyClass: NSObject {
let myProperty: String
init() {
myProperty = MyClass.setupMyProperty()
super.init()
}
class func setupMyProperty() -> String {
return "foo"
}
}
答案 2 :(得分:3)
您不能使用self
,直到您的实例内存完全初始化(此时您无法再设置常量属性),因此指定初始化程序的顺序必须做的事情是:
self
,调用方法等我不确定对于常量属性的情况是否有一个很好的解决方法。一种替代方法是将属性声明为隐式展开的可选项,因此它最初设置为nil:
class MyClass {
var myProperty: String!
init() {
super.init() // only if you actually have a superclass, and make sure this does not use `myProperty`
self.setupMyProperty()
}
func setupMyProperty() {
myProperty = "x"
}
}
小心这一点,它会失去一些类型安全性,因为myProperty
现在可以是nil
,如果是,当您尝试访问它时,它将导致运行时错误。所以只有这样做才能确保它被所有指定的初始化程序初始化,而不是被初始化程序链中setupMyProperty()
之前调用的任何东西使用(例如,当超类初始化程序调用方法时)覆盖访问myProperty
),并且永远不会明确地设置为nil。
另外,参见the docs,特别是上面我解释的整个调用顺序的类继承和初始化部分。
答案 3 :(得分:1)
尝试将setupMyProperty()置于常量中。然后它在你初始化之前存在,你可以从init()调用它。您甚至可以按如下方式访问参数:
class MyClass {
var myProperty: String
let setupMyProperty : (String) -> (void) = {
param in
self.myProperty = param
}
init(x: String) {
// removed redundant line: super.init()
self.setupMyProperty(x)
}
}
答案 4 :(得分:0)
class MyClass {
let myProperty: String
init() {
super.init()
self.myProperty = {
// do your logic here
return "x"
}()
}
}