假设我在Swift中有以下类(它有明显的问题)
class MyClass {
let myProperty: String
init() {
super.init()
self.setupMyProperty()
}
func setupMyProperty() {
myProperty = "x"
}
}
这过于简化了,但我基本上是试图将myProperty
的初始化委托给setupMyProperty()
方法。这是我经常用来分解类设置的不同部分的模式。
但是当然,在超级初始化器运行之前我不能调用self
,在所有属性都设置好之前我不能运行超级初始化器,所以我处于第22条军规中。最重要的是,由于setupMyProperty()
不被认为是初始化器,因此无论如何都不能分配myProperty
。
谁能告诉我如何在Swift中实现这个模式?
6条答案
按热度按时间sbdsn5lh1#
将其声明为隐式展开的可选
来源:Swift文档,Unowned References和Implicitly Unwrapped Optional Properties
wmtdaxz32#
setupMyProperty
是否需要访问self?如果没有,你可以用一个类方法来实现:dz6r00yl3#
在示例的内存完全初始化之前,你不能使用
self
(此时你不能再设置常量属性),所以你指定的初始化器必须做的事情的顺序是:1.初始化该类添加的所有属性
1.调用超类初始化器(如果有超类)
1.现在你可以使用
self
,调用方法,等等我不确定是否有一个很好的工作区的情况下,一个恒定的属性。一种替代方法是将属性声明为隐式展开的可选属性,因此它最初设置为nil:
要小心,它失去了一点类型安全性,因为
myProperty
现在可以是nil
,如果当您尝试访问它时,它将导致运行时错误。所以只有当你确定它会被你指定的所有初始化器初始化,而不是被初始化器链中setupMyProperty()
之前调用的任何东西使用时才这样做(例如:当一个超类初始化器调用一个你覆盖的访问myProperty
的方法时),并且永远不要显式地设置为nil。另外,请参阅文档,特别是关于类继承和初始化的部分,我在上面解释了整个调用顺序的内容。
du7egjpx4#
尝试将setupMyProperty()放入常量中。在初始化之前,它就在那里了,你可以从init()调用它。您甚至可以按以下方式访问参数:
hmae6n7t5#
fzwojiic6#
惊讶地看到最高投票的答案。使用一个 * 隐式展开的可选 * 会带来很大的安全风险。
如果你想重置你的属性,但要保留一个真实的来源,请使用
Constants
结构体如果你想在init中隐藏复杂的设置逻辑,可以使用
static func
如果你想为一个对象使用不同的初始化器,请使用
Constants
结构体和初始化逻辑