An initializer is a special type of function that is used to create an object of a class or struct.
In Swift, we use the init()
method to create an initializer. For example,
class Wall {
...
// create an initializer
init() {
// perform initialization
...
}
}
Here, the method init()
is an initializer of the class Wall.
Example: Swift Initializer
// declare a class
class Wall {
var length: Double
// initializer to initialize property
init() {
length = 5.5
print("Creating a wall.")
print("Length = ", length)
}
}
// create an object
var wall1 = Wall()
Output
Creating a wall. Length = 5.5
In the above example, we have created an initializer named init()
. Inside the initializer, we have initialized the value of the length property.
Notice the following statement:
// create an object
var wall1 = Wall()
Here, when the wall1 object is created, the init()
initializer is called. And, the value of the length property is initialized to 5.5.
Parameterized Initializer
A Swift initializer can also accept one or more parameters. Such initializers are known as parameterized initializers (initializers with parameters).
Let's see an example,
class Wall {
var length: Double
...
// initializer with parameter
init(length: Double) {
self.length = length
}
}
// create an object
var wall1 = Wall(length: 10.5)
Here,
init(length: Double)
- initializer with parameter lengthvar wall1 = Wall(length: 10.5)
- pass value 10.5 to the parameter lengthself.length = length
- assigns the value of the length parameter (10.5) to the length propertyself.length
- specify that the length property is associated with the current object which is wall1
Example: Parameterized Initializer
// declare a class
class Wall {
var length: Double
var height: Double
// parameterized initializer to initialize properties
init(length: Double, height: Double) {
self.length = length
self.height = height
}
func calculateArea() -> Double {
return length * height
}
}
// create object and initialize data members
var wall1 = Wall(length: 10.5, height: 8.6)
var wall2 = Wall(length: 8.5, height: 6.3)
print("Area of Wall 1: ", wall1.calculateArea())
print("Area of Wall 2: ", wall2.calculateArea())
Output
Area of Wall 1: 90.3 Area of Wall 2: 53.55
In the above example, we have created an initializer init()
with two parameters: length and height. Notice the expressions,
var wall1 = Wall(length: 10.5, height: 8.6)
var wall2 = Wall(length: 8.5, height: 6.3)
Here, while creating an object of the Wall class, we pass the values for the member properties as arguments.
With the member variables thus initialized, we can now calculate the area of the wall with the calculateArea()
method.
Initializer Overloading
Swift Initializers can be overloaded in a similar way as function overloading.
In initializer overloading, two or more initializers can have the same name if they have different types or numbers of parameters.
And, based on the arguments passed during the object creation, the corresponding initializer is called.
Let's see an example,
class Person {
var age: Int
// 1. initializer with no arguments
init() {
age = 20
}
// 2. initializer with an argument
init(age: Int) {
self.age = age
}
// method to return age
func getAge() -> Int {
return age
}
}
var person1 = Person()
var person2 = Person(age: 23)
print("Person1 Age:", person1.getAge())
print("Person1 Age:", person2.getAge())
Output
Person1 Age: 20 Person1 Age: 23
In the above example, we have created a class Person that has a single property age.
We have also defined two initializers: init()
and init(age: Int)
.
- We have not passed any argument to the person1 object, so the first initializer is called. Hence, age is initialized to 20.
- We have passed 23 as an argument to person2. So, the second initializer is called and age is initialized to 23.
The method getAge()
returns the value of age, and we use it to print the age of person1 and person2.
Swift convenience Initializer
In previous examples, the initializer we defined were primary initializers of the class. These primary initializers are also called designated initializers.
However, we can also define a secondary/supporting initializer for a class called convenience initializer.
To define a convenience initializer, we use the convenience
keyword before the initializer. For example,
class University {
var name : String
var rank : String
init(name : String, rank: String) {
self.name = name
self.rank = rank
}
// define convenience init
convenience init() {
self.init(name: "Kathmandu University", rank: "1st")
}
}
var university1 = University()
print(university1.name)
print("Rank:", university1.rank)
Output
Kathmandu University Rank: 1st
In the above example, we have created a designated initializer: init()
and a convenience initializer: convenience init()
.
Inside the convenience initializer, we have called the designated initializer and assigned values to the properties.
convenience init() {
self.init(name: "Kathmandu University", rank: "1st")
}
When the university1 object is created, the convenience initializer is called.
// using convenience initializer
var university1 = University()
This makes our code look cleaner compared to calling the designated initializer:
// call designated initializer
var university1 = University(name: "Kathmandu University", rank: "1st")
Note: Convenience Initializers are useful when it comes to assigning default values to stored properties.
Failable Initializer
In some cases initializers might or might not work, this is called a failable initializer.
We write a failable initializer by placing a question mark (?)
after the init
keyword and return nil
if something goes wrong. For example,
class File {
var folder: String
// failable initializer
init?(folder: String) {
// check if empty
if folder.isEmpty {
print("Folder Not Found") // 1st output
return nil
}
self.folder = folder
}
}
// create folder1 object
var file = File(folder: "")
if (file != nil) {
print("File Found Successfully")
}
else {
print("Error Finding File") // 2nd output
}
Output
Folder Not Found Error Finding File
In the above example, we have created the failable initializer init?()
with a parameter named folder.
And, we have used the if
statement and the isEmpty
property
if (folder.isEmpty) { return nil }
to check if the folder is empty and returns nil
if it is empty.
For the folder1 object, we have passed an empty string ""
which triggers an initialization failure, so the statement inside it is executed first and then it returns nil
.
And finally, the statement inside the else
block is executed
Memberwise Initializer for structs
In Swift, we are not required to create an initializer while working with structs. Swift automatically generates a memberwise for us. For example,
struct Person {
var name: String
var age: Int
}
Here, we have not created any initializer inside the Person struct. However, Swift auto generates a memberwise initializer for us,
var person1 = Person(name: "Dwight", age: 43)
Here, values inside the parentheses ()
are automatically assigned to corresponding properties of the struct. This is called a memberwise initializer.
Example: Memberwise Initializer
struct Person {
// define two properties
var name: String
var age: Int
}
// object of Person with memberwise initializer
var person1 = Person(name: "Dwight", age: 43)
print("Name:", person1.name)
print("Age:", person1.age)
Output
Name: Dwight Age: 43
In the above example, we have used the auto-generated memberwise initializer to assign values to corresponding properties of the Person struct.
var person1 = Person(name: "Dwight", age: 43)
Here, the value of name is set to Dwight
, and age is set to 43.