Swift: why can't I call a method from an override of init?

I have the following code example (from 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() 

You may notice that I applied the createUUID method as static.

But why can't I call this method from init non-static ?:

 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() 

Without inheritance, it works correctly:

 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() 
+5
source share
3 answers

There are two competing initialization security checks that cause problems.

Security Check 1

The designated initializer must ensure that all properties introduced by its class are initialized before it delegates to the superclass initializer.

and

Security Check 4

The initializer cannot call any instance methods, read the values ​​of any properties of the instance, or refer to self as a value until the completion of the first phase of initialization.

Here's how it works.

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

on the contrary

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

Thanks to @Ruben in my answer

+8
source

Initialization in Swift with inheritance is quite a challenge. Before calling super.init() , all instances of instances of the child objects must be created, but you must call super.init() before you can call the methods in the self object.

My suggestion is to give uuid temporary value before calling super.init() and then generate uuid with your instance method:

 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 is a link to initialize in Swift to classes that inherit from other classes. This is quite a long time, but you can summarize it as:

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

But you can also read about convenience initializers there, which are pretty handy.

+4
source

That is why there are implicit Unwrapped Optionals.

"Implicitly deployed optional options are useful when it is confirmed that the value of optionals exists immediately after the option is first defined and it is probably definitely assumed that it exists at every point after that. The main use of implicitly deployed options in Swift is during class initialization ( ...) "

Excerpt from: Apple Inc. "Fast programming language (Swift 3)." interactive books. https://itun.es/gb/jEUH0.l

All you have to do is implicityly unrapp uuid:

 class Device: Serializable { var uuid: String! override init() { super.init() self.uuid = createUUID() } func createUUID() -> String { return "XXX2" } } 
+3
source

Source: https://habr.com/ru/post/1213045/


All Articles