Default Initializers
Memberwise Initializers for Structure Types
Structure types can enlist the properties by a memberwise initializer, which is a kind of defalut initializer.
struct Size {
var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)
And you even can omit values of any properties that have default values.
let zeroByTwo = Size(height: 2.0)
print(zeroByTwo.width, zeroByTwo.height)
// Prints "0.0 2.0"
let zeroByZero = Size()
print(zeroByZero.width, zeroByZero.height)
// Prints "0.0 0.0"
Initializer Delegation for Value Types
If we want our custom value type to be initializable with the default initializer and memberwise initializer, and also with our own custom initializers, write our custom initializers in an extension rather than as part of the value type’s original implementation
struct Rect {
var origin = Point()
var size = Size()
init() {}
init(origin: Point, size: Size) {
self.origin = origin
self.size = size
}
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
As the example above, we have three initilizers, when we init Rect
, it will call the Size()
and Point()
autoly, and we can see the third one, we call self.init()
within customer initializer to make a new value.
Class Inheritance and Initialization
Syntax for Designated and Convenience Initializers
init(parameters) {
statements
}
convenience init(parameters) {
statements
}
Initializer Delegation for Class Types
Designated initializers must always delegate up.
Convenience initializers must always delegate across.
Initializer Inheritance and Overriding
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
class Bicycle: Vehicle {
override init() {
super.init()
numberOfWheels = 2
}
}
class Hoverboard: Vehicle {
var color: String
init(color: String) {
self.color = color
// super.init() implicitly called here
}
override var description: String {
return "\(super.description) in a beautiful \(color)"
}
}
We can see the example above, the Bicycle
class inherit Vehical
and override init()
, so we can call the super.init()
manually.
But if we just implement init()
without override
just list Hoverboard
, the super.init()
will be called implicitly at the end of init()
, I don't like any implicit thing actually, so I suggest we’d be better to use the override
always to make it clearer.
Automatic Initializer Inheritance
In ordiray way, the subclass will not inherit the initailizers of superclass, but except for the following two cirmustace.
For designated initailizers, if subclass have no one, it can inherit its superclass’s.
For convenience initializers, if subclass dosen’t have any designated initailizers or do have all designated initailizers, it can inherit all convenience initializers of its superclass.
… to be honest, I cannot say anyting when I read these, but it needs to be noted.
Failable Initializers
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty { return nil }
self.species = species
}
}
We can use init?()
to define a initializer to make sure to create a new instance correctly otherwise we will get nil
.
Required Initializers
class SomeClass {
required init() {
// initializer implementation goes here
}
}
class SomeSubclass: SomeClass {
required init() {
// subclass implementation of the required initializer goes here
}
}
If a superclass use required
keyword to modify a initializer which means each subclass inherit it must implement this initializer and override it implicitly. And the required initializer must be modified by required
also.
Deinitialization
Just as OC, we also can use deinit
keyword to implement a deinitialization function.
deinit {
// perform the deinitialization
}
Without any prarameters and parentheses.
Let’s think!