从Swift初始化程序调用方法

时间:2014-06-09 11:08:39

标签: swift

让我们说我在Swift中有以下类(有明显的问题)

class MyClass {
    let myProperty: String

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

    func setupMyProperty() {
        myProperty = "x"
    }
}

这过于简化,但我基本上试图将myProperty的初始化委托给setupMyProperty()方法。这是我经常用来打破课堂设置不同部分的模式。

但是,当然,在超级初始化程序运行之前我无法调用self,并且我无法运行超级初始值设定项,直到所有属性都已设置为止,因此我可以使用超级初始化程序。最后,由于setupMyProperty()不被视为初始化程序,因此无论如何都无法指定myProperty

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

5 个答案:

答案 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,直到您的实例内存完全初始化(此时您无法再设置常量属性),因此指定初始化程序的顺序必须做的事情是:

  1. 初始化此类添加的所有属性
  2. 调用超类初始值设定项(如果有超类)
  3. 现在您可以使用self,调用方法等
  4. 我不确定对于常量属性的情况是否有一个很好的解决方法。一种替代方法是将属性声明为隐式展开的可选项,因此它最初设置为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" 
        }()
    }
}