I have 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 can notice that I implemented createUUID
method as static.
But why I can't call this method from init
not in static way? :
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 properly:
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()
Override initializer In Swift initializers are not inherited for subclasses by default. If you want to provide the same initializer for a subclass that the parent class already has, you have to use the override keyword.
Overriding init()Override the class initializer init() to initialize or allocate resources for the servlet instance's life, such as a counter. The init() method runs after the servlet is instantiated but before it accepts any requests.
This is called class inheritance or subclassing, the class you inherit from is called the “parent” or “super” class, and the new class is called the “child” class. For safety reasons, Swift always makes you call super. init() from child classes – just in case the parent class does some important work when it's created.
There are two competing initialization safety checks that are causing your problem.
Safety check 1
A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.
and
Safety check 4
An initializer cannot call any instance methods, read the values of any instance properties, or refer to self as a value until after the first phase of initialization is complete.
Here is how it works.
override init() {
super.init() // Fails safety check 1: uuid is not initialized.
uuid = createUUID()
}
conversely,
override init() {
uuid = createUUID() // Fails safety check 4: cannot call an instance method before initialization is complete.
super.init()
}
Thanks to @Ruben in his answer
This is exactly why Implicitly Unwrapped Optionals exists.
“Implicitly unwrapped optionals are useful when an optional’s value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter. The primary use of implicitly unwrapped optionals in Swift is during class initialization(...)”
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 3).” iBooks. https://itun.es/gb/jEUH0.l
All you need to do is implicityly unwrapp uuid:
class Device: Serializable {
var uuid: String!
override init() {
super.init()
self.uuid = createUUID()
}
func createUUID() -> String {
return "XXX2"
}
}
Initialization in Swift with inheritance is kind of tricky.
You must have all your child object's instance variables instantiated before you can call super.init()
, and yet you need to call super.init()
before you can call methods on the self
object.
My suggestion is to give uuid
a temporary value before you call super.init()
, and then generate the uuid
with your instance method afterwards:
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 the reference for initialization in Swift on classes that inherit from other classes. It is pretty long, 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 too, which are pretty handy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With