从Swift初始化程序调用方法

mpr*_*vat 36 swift

假设我在Swift中有以下类(它有明显的问题)

class MyClass {
    let myProperty: String

    init() {
        super.init()
        self.setupMyProperty()
    }

    func setupMyProperty() {
        myProperty = "x"
    }
}
Run Code Online (Sandbox Code Playgroud)

这是过度简化,但我基本上试图将初始化委托myPropertysetupMyProperty()方法.这是我经常使用的模式来分解类的设置的不同部分.

但是当然,self在超级初始化程序运行之前我无法调用,并且在所有属性都已设置之前我无法运行超级初始化程序,因此我处于捕获状态22.最重要的是它setupMyProperty()不是被认为是初始化程序,myProperty无论如何都无法分配.

谁能告诉我如何在Swift中实现这种模式?

Lom*_*baX 38

将其声明为隐式解包的可选项

class MyClass : NSObject {
    var myProperty: String!

    init() {
        super.init()
        self.setupMyProperty()
    }

    func setupMyProperty() {
        self.myProperty = "x"
    }
}
Run Code Online (Sandbox Code Playgroud)

"Swift编程语言"手册第499页

  • 这样做不会失去一些安全感吗?我想我必须确保在访问该属性之前对其进行初始化,否则会出现运行时错误。对于此实例,它不能是常量。我想这是我见过的最好的方式,只是不完美 (2认同)
  • 那么没有办法让 myProperty 保持常量(let)吗? (2认同)
  • Apple有新的官方解决方案吗?什么是新的,进化的?你有更新的信息,你可以提供一个链接,以便我可以更新我的答案.或者,如果您愿意,可以添加自己的答案 (2认同)

Bil*_*ill 9

是否setupMyProperty需要访问的自我?如果没有,您可以使用类方法实现此目的:

class MyClass: NSObject {
    let myProperty: String

    init() {
        myProperty = MyClass.setupMyProperty()
        super.init()
    }

    class func setupMyProperty() -> String {
        return "foo"
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这里的问题是当它与简单的例子一起工作时,整点是在sub方法中初始化一组属性. (2认同)

Luk*_*kas 7

在实例的内存完全初始化之前您不能使用self(此时您不能再设置常量属性),因此您指定的初始化程序必须执行操作的顺序是:

  1. 初始化该类添加的所有属性
  2. 调用超类初始值设定项(如果有超类)
  3. 现在你可以使用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"
    }
}
Run Code Online (Sandbox Code Playgroud)

请小心这一点,它会失去一点类型安全性,就像myProperty现在一样nil,如果是这样,当您尝试访问它时,它将导致运行时错误。因此,只有当您确定它将由所有指定的初始值设定项初始化,并且不会被初始值设定项链中之前调用的任何内容使用时才执行此操作setupMyProperty()(例如,当超类初始值设定项调用您重写访问的方法时myProperty),并且永远不会设置为明确为零。

另外,参见。文档,特别是我上面解释的整个调用顺序内容的类继承和初始化部分。

  • `private(set) var myProperty: String` 将防止外部对您的属性值进行恶意更改 (2认同)