Swift:为什么我不能从override init调用方法?

时间:2015-02-10 11:53:35

标签: swift

我有以下代码示例(来自PlayGround):

class Serializable : NSObject{
override init() { }
}

class Device : Serializable{

    var uuid:String

    override init() {

        println("init ")

        self.uuid = "XXX"

       self.uuid = Device.createUUID()

        println(self.uuid)

    }

   class func createUUID() -> String{
       return "XXX2"
    }
}


var device = Device()

您可以注意到我将createUUID方法实现为静态。

但为什么我不能以静态的方式从init调用此方法? :

class Serializable : NSObject{
override init() { }
}

class Device : Serializable{

    var uuid:String

    override init() {

        // tried
        // super.init()

        println("init ")

        self.uuid = "XXX"

       self.uuid = self.createUUID() //  ERROR
       self.uuid = createUUID() // ERROR

        println(self.uuid)

        // tried
        // super.init()

    }

  func createUUID() -> String{
       return "XXX2"
    }
}


var device = Device()

没有继承,它可以正常工作:

class Device {

    var uuid:String

     init() {

        println("init ")

        self.uuid = "XXX"

       self.uuid = self.createUUID()

        println(self.uuid)

    }

    func createUUID() -> String{
       return "XXX2"
    }
}


var device = Device()

3 个答案:

答案 0 :(得分:9)

有两个竞争initialization safety checks导致您的问题。

  

安全检查1

     

指定的初始化程序必须确保在委托一个超类初始化程序之前初始化其类引入的所有属性。

  

安全检查4

     

初始化程序无法调用任何实例方法,读取任何实例属性的值,或者在初始化的第一阶段完成之后将self作为值引用。

以下是它的工作原理。

override init() {
    super.init() // Fails safety check 1: uuid is not initialized.
    uuid = createUUID()
}

相反,

override init() {
    uuid = createUUID() // Fails safety check 4: cannot call an instance method before initialization is complete.
    super.init()
}

感谢@Ruben in his answer

答案 1 :(得分:4)

使用继承在Swift中初始化有点棘手。 您必须先实例化所有子对象的实例变量,然后才能调用super.init(),然后在调用super.init()对象上的方法之前需要调用self

我的建议是在致电uuid之前给super.init()一个临时值,然后使用您的实例方法生成uuid

class Device : Serializable{

    var uuid:String

    override init() {
        // First you need to initialize this classes instance variables
        // This feels a little silly to put in a temporary value, but if you don't want to use an optional, then it is necessary
        self.uuid = ""

        // Next you need to initialize super before you can use the `self` object
        super.init()

        // Since you are calling `createUUID()`, you are calling an instance method on the `self` object
        // Your object must call `super.init()` before you can do so
        self.uuid = self.createUUID()
    }

    func createUUID() -> String{
        return "XXX2"
    }
}

Here是在Swift中对从其他类继承的类进行初始化的引用。它很长,但你可以总结为:

override init() {
    // Make sure all instance variables for the child class are instantiated
    super.init()
    // Do other initialization that requires the `self` object here
}

但你也可以在那里阅读便利初始化器,这非常方便。

答案 2 :(得分:4)

这正是Implicitly Unwrapped Optionals存在的原因。

“当首次定义可选项后立即确认可选项的值存在时,隐式展开的选项很有用,并且可以肯定假定存在于此后的每个点。 Swift中隐式解包选项的主要用途是在类初始化(...)“

期间

摘自:Apple Inc.“Swift编程语言(Swift 3)。”iBooks。 https://itun.es/gb/jEUH0.l

你需要做的就是明智地解开uuid:

class Device: Serializable {

    var uuid: String!

    override init() {
        super.init()
        self.uuid = createUUID()
    }

    func createUUID() -> String {
        return "XXX2"
    }
}