”;
Initializers are used to create instances of class, structure or enumeration. It makes sure that all properties of the instance are set to suitable initial values before the use of the instance. If we do not create an initializer in the class, structure or enumeration, then Swift will automatically create an initializer for the instances.
They do not return any value; their main goal is to make sure that the new instance of any type is initialized correctly before it will be used for the first time. Swift also provides a de-initialization process for performing memory management operations once the instances are deallocated.
Defining Initializer in Swift
In Swift, the initializer is created by using the init keyword. It may or may not have parameters.
Syntax
Following is the syntax of the initializer −
init() { //New Instance initialisation goes here }
Example
Here the structure ”rectangle” is initialized with members’ length and breadth as ”Double” datatypes. Init() method is used to initialize the values for the newly created members length and double. The area of a rectangle is calculated and returned by calling the rectangle function.
struct rectangle { var length: Double var breadth: Double // Initializer init() { length = 6 breadth = 12 } } var area = rectangle() print("area of rectangle is (area.length*area.breadth)")
Output
It will produce the following output −
area of rectangle is 72.0
While creating an instance of any particular type always remember the stored properties must be initialised before the instance is created. They can’t be left in an indeterminate state. We can initialize stored properties either in the instance or by assigning a default value as part of their definition.
Setting Property Values by Default
We can initialize the stored property using the init() initializer or the user has a provision to initialize the property values by default while declaring the class or structure members. When the property takes the same value alone throughout the program we can declare it in the declaration section alone rather than initializing it in init().
Example
struct rectangle { // Properties with default value var length = 6 var breadth = 12 } // Instance of rectangle structure var area = rectangle() print("Area of rectangle is (area.length*area.breadth)")
Output
It will produce the following output −
Area of rectangle is 72
Parameters Initialization
We are allowed to initialize the properties of the instance by passing parameters to the initializer. It is the part of the initializer”s definition using init().
Example
// Structure struct Rectangle { // Properties var length: Double var breadth: Double var area: Double // Initializer with parameters init(fromLength length: Double, fromBreadth breadth: Double) { self.length = length self.breadth = breadth area = length * breadth } } // Instance of structure let ar = Rectangle(fromLength: 6, fromBreadth: 12) print("area is: (ar.area)")
Output
It will produce the following output −
area is: 72.0
Local & External Parameters
Initialization parameters have both local and global parameter names similar to those of function and method parameters. Local parameter declaration is used to access within the initialize body and external parameter declaration is used to call the initializer.
Swift initializers differ from function and method initializers in that they do not identify which initializers are used to call which functions.
So to overcome this, Swift introduces an automatic external name for every parameter in init(). This automatic external name is equivalent to the local name written before every initialization parameter.
Example
struct Days { // Properties let sunday, monday, tuesday: Int // Initializer with parameter names init(sunday: Int, monday: Int, tuesday: Int) { self.sunday = sunday self.monday = monday self.tuesday = tuesday } } // Instance of structure let week = Days(sunday: 1, monday: 2, tuesday: 3) print("Days of a Week is: (week.sunday)") print("Days of a Week is: (week.monday)") print("Days of a Week is: (week.tuesday)")
Output
It will produce the following output −
Days of a Week is: 1 Days of a Week is: 2 Days of a Week is: 3
Parameters without External Names
When an external name is not needed for an initialize underscore ”_” is used to override the default behavior.
Example
struct Rectangle { var length: Double init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } init(_ area: Double) { length = area } } let rectarea = Rectangle(180.0) print("area is: (rectarea.length)") let rearea = Rectangle(370.0) print("area is: (rearea.length)") let recarea = Rectangle(110.0) print("area is: (recarea.length)")
Output
It will produce the following output −
area is: 180.0 area is: 370.0 area is: 110.0
Optional Property Types
When the stored property at some instance does not return any value that property is declared with an ”optional” type indicating that ”no value” is returned for that particular type. The property that was declared as ”optional” will automatically initialize with nil value during initialization.
Example
struct Rectangle { // Optional property type var length: Double? init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } init(_ area: Double) { length = area } } // Instances of structure let rectarea = Rectangle(180.0) print("area is: (rectarea.length)") let rearea = Rectangle(370.0) print("area is: (rearea.length)") let recarea = Rectangle(110.0) print("area is: (recarea.length)")
Output
It will produce the following output −
area is: Optional(180.0) area is: Optional(370.0) area is: Optional(110.0)
Assigning Constant Properties During Initialization
We are allowed to assign a value to a constant at the time of initialization and once the constant property is assigned a value we cannot modify that value further, if we try to do we will get an error. Also, a constant property of the class instance can be modified during the initialization by the class in which it is introduced not by the subclass.
Example
class Rectangle { // Constant property let length: Int var breadth: Int // Initializer init(breadth: Int) { self.breadth = breadth // Assigning a value to the constant property during initialization self.length = 34 } // Method using constant property func area() -> Int { return length * breadth } } // Creating an instance let obj = Rectangle(breadth: 10) // Accessing the constant property print("The value of length is: (obj.length)") let ar = obj.area() print("The area of the Rectangle is: (ar)")
Output
It will produce the following output −
The value of length is: 34 The area of the Rectangle is: 340
Default Initializers
Default initializers are those initializers that are automatically created by the Swift compiler when a class or structure does not contain any customised initialiser or all the properties have default values. They are used to create instances of a class or structure with all its properties set to their default values.
Example
class defaultexample { // Properties with default value var stmark = 98 var pass = true } // Creating an instance with default initializer var result = defaultexample() // Accessing properties print("result is: (result.stmark)") print("result is: (result.pass)")
Output
It will produce the following output −
result is: 98 result is: true
Memberwise Initializers for Structure Types
In Swift, if a structure type does not have its custom initializer, then it will automatically receive the ”memberwise initializer’. They also receive the ”memberwise initializer’ if they have stored properties that do not contain default values. The new instance properties are passed to the memberwise initialize by name.
Example
struct Rectangle { var length = 100.0, breadth = 200.0 } // Instance with memberwise initializers let area = Rectangle(length: 24.0, breadth: 32.0) print("Area of rectangle is: (area.length)") print("Area of rectangle is: (area.breadth)")
Output
It will produce the following output −
Area of rectangle is: 24.0 Area of rectangle is: 32.0
Initializer Delegation
Initializer Delegation is defined as calling initializers from other initializers. Its main function is to act as reusability to avoid code duplication across multiple initializers.
Rules for Initializer Delegation
Following are some rules that an initializer delegation follows while working with values types and class types −
For Value Types (Structures and Enumerations)
-
Inheritance is not supported for value types. So the initializer delegation for value types calls another initializer within the same type.
-
It does not have any concept of subclass. Hence the designated initializers are the main initializers for complete initialization.
-
Value types use self.init to refer to other initializers of the same value type.
-
They automatically receive a member wise initializer for their properties.
For Class types
-
Inheritance is supported. Hence the classes have to make sure that all the stored properties they inherit must be assigned with a suitable value during initialization.
-
It has the concept of subclass. Hence the designated initializers in a class can call the designated initializers of its immediate super class using super.init.
Example
Swift program to demonstrate initializer delegation for value types.
struct Car { var price: Int var quantity: Int // Designated initializer init(price: Int, quantity: Int) { self.price = price self.quantity = quantity } // Convenience initializer delegating to the designated initializer init(monzaCar: Int) { self.init(price: monzaCar, quantity: monzaCar) } // Convenience initializer with default values init() { self.init(price: 2245622, quantity: 1) } } // Creating instances let obj1 = Car(price: 2000000, quantity: 1) let obj2 = Car(monzaCar: 34) let obj3 = Car() print(obj1) print(obj2) print(obj3)
Output
It will produce the following output −
Car(price: 2000000, quantity: 1) Car(price: 34, quantity: 34) Car(price: 2245622, quantity: 1)
Class Inheritance and Initialization
As we all know a class has stored properties including the properties it inherits from the superclass. So all these properties must be initialised with an initial value at the time of initialization. So to initialize these properties Swift provides two types of initializers and they are −
Designated Initializer
It is the main initialiser for a class. It initializes all the properties of the class and can also initialize inherited properties by calling the superclass initializer. At least one designated initializer is defined for every class.
Syntax
Following is the syntax for the designated initializer −
init(parameterList) { // Statement }
Example
Swift program to demonstrate how to create designated initializers.
// Super class class mainClass { var no1 : Int // Designated Initializer init(no1 : Int) { self.no1 = no1 } } // Sub class class subClass : mainClass { var no2 : Int // Designated Initializer init(no1 : Int, no2 : Int) { self.no2 = no2 // Calling designated initializer of super class to initialize no1 super.init(no1:no1) } } // Creating instances let obj1 = mainClass(no1: 10) let obj2 = subClass(no1: 10, no2: 20) print("no1:", obj1.no1) print("no1:(obj2.no1) and no2: (obj2.no2)")
Output
It will produce the following output −
no1: 10 no1:10 and no2: 20
Convenience Initializer
It is the supporting initialize for a class. It can be implemented to invoke a designated initializer within the same class, wherein certain parameters of the designated initializer are assigned default values. It can also create an instance for a specific use case or input value type. A class doesn”t need to have a convenience initializer.
Syntax
Following is the syntax for the convenience initializer −
convenience init(parameterList) { // Statement }
Example
Swift program to demonstrate how to create convenience initializers.
class mainClass { var no1 : Int // Designated Initializer init(no1 : Int) { self.no1 = no1 } } class subClass : mainClass { var no2 : Int // Designated Initializer init(no1 : Int, no2 : Int) { self.no2 = no2 super.init(no1:no1) } // Requires only one parameter for convenient method override convenience init(no1: Int) { self.init(no1:no1, no2:0) } } // Creating instances let obj1 = mainClass(no1: 20) let obj2 = subClass(no1: 30, no2: 50) print("res is: (obj1.no1)") print("res is: (obj2.no1)") print("res is: (obj2.no2)")
Output
It will produce the following output −
res is: 20 res is: 30 res is: 50
Initializer Inheritance and Overriding
Swift does not allow its subclasses to inherit its superclass initializers for their member types by default. They can call the initializer of its superclass with the help of super.init() to make sure that all the inherited properties are initialized with some values.
We are allowed to override the designated initializer of the superclass in their subclass with the help of the override keyword. The overriding initializer must have to call the corresponding initializer in their superclass with the help of super.init().
As we know a subclass cannot inherit their superclass initialiser by default. However, if the superclass initializers can meet the following condition then they can automatically inherited by their subclasses −
-
If the subclass does not have any designated initializers, then it will automatically inherit its base class’s designated initializers.
-
If the subclass provides the implementation of all its base class’s designated initializers then it will automatically inherit all base class’s convenience initializers.
Example
Swift program to demonstrate how to override initializer.
// Base class class Sides { var corners = 4 var description: String { return "(corners) sides" } } // Instance of sides class let rectangle = Sides() print("Rectangle: (rectangle.description)") // Subclass class Pentagon: Sides { // Overriding initializer override init() { super.init() corners = 5 } } // Instance of Pentagon class let bicycle = Pentagon() print("Pentagon: (bicycle.description)")
Output
It will produce the following output −
Rectangle: 4 sides Pentagon: 5 sides
Example
Swift program to demonstrate how designated and convenience initializers in action.
class Planet { var name: String init(name: String) { self.name = name } convenience init() { self.init(name: "[No Planets]") } } let plName = Planet(name: "Mercury") print("Planet name is: (plName.name)") let noplName = Planet() print("No Planets like that: (noplName.name)") class planets: Planet { var count: Int init(name: String, count: Int) { self.count = count super.init(name: name) } override convenience init(name: String) { self.init(name: name, count: 1) } }
Output
It will produce the following output −
Planet name is: Mercury No Planets like that: [No Planets]
Failable Initializer
Not all the initializers can initialize values successfully they can fail due to: Invalid parameter values, the absence of a required external source, or a condition preventing initialization from succeeding.
So to catch exceptions thrown by the initialization method, Swift provides a special type of initializer that is a ”failable initializer’. A failable initializer notifies the developer that something is left unnoticed while initializing the structure, class or enumeration members. Or we can say that a failable initializer creates an optional value of type it initializes. If a failure triggers, then this initializer will return nil. A class, structure or enumeration can have one or more failable initializers to catch the fail.
Using the init? keyword we can create a failable initializer. Also, failable and non-failable initializers cannot be defined with the same parameter types and names.
Syntax
Following is the syntax for the failable initializer −
init?(parameterList) { // Statement }
Example
Swift program to demonstrate how to create failable initializers.
struct studrecord { let stname: String // Failable initializer init?(stname: String) { if stname.isEmpty {return nil } self.stname = stname } } let stmark = studrecord(stname: "Swing") if let name = stmark { print("Student name:(name) is specified.") } let blankname = studrecord(stname: "") if blankname == nil { print("nStudent name is left blank") }
Output
It will produce the following output −
Student name:studrecord(stname: "Swing") is specified. Student name is left blank
Failable Initializers for Enumerations
In Swift, we are allowed to use failable initializers for enumerations too to notify the user when the enumeration members are left from initializing values. It selects proper enumeration cases according to one or more parameters and the initializer can fail if the given parameter does not match to the specified enumeration case.
Example
Swift program to demonstrate failable initializers for enumerations.
// Enumeration enum functions { case a, b, c, d // Failable initializer init?(funct: String) { switch funct { case "one": self = .a case "two": self = .b case "three": self = .c case "four": self = .d default: return nil } } } let result = functions(funct: "two") if result != nil { print("With In Block Two") } let badresult = functions(funct: "five") if badresult == nil { print("Block Does Not Exist") }
Output
It will produce the following output −
With In Block Two Block Does Not Exist
Failable Initializers for Classes
A failable initializer when declared with enumerations and structures alerts an initialization failure at any circumstance within its implementation. However, a failable initializer in classes will alert the failure only after the stored properties have been set to an initial value.
Example
Swift program to demonstrate failable initializers for classes.
// Class class studrecord { let studname: String! // Failure Initializer init?(studname: String) { self.studname = studname if studname.isEmpty { return nil } } } if let stname = studrecord(studname: "Failable Initializers") { print("Module is (stname.studname!)") }
Output
It will produce the following output −
Module is Failable Initializers
Overriding a Failable Initializer
Just like the initializer we are allowed to override a superclass failable initializer inside the subclass. Super class failable initialize can also be overridden within a sub-class non-failable initializer. Subclass initializer cannot delegate up to the superclass initializer when overriding a failable superclass initializer with a non-failable subclass initialize. Whereas a non-failable initializer can never be delegated to a failable initializer.
Example
Swift program to demonstrate overriding failable initializers.
class Planet { var name: String init(name: String) { self.name = name } convenience init() { self.init(name: "[No Planets]") } } let plName = Planet(name: "Mercury") print("Planet name is: (plName.name)") let noplName = Planet() print("No Planets like that: (noplName.name)") class planets: Planet { var count: Int init(name: String, count: Int) { self.count = count super.init(name: name) } override convenience init(name: String) { self.init(name: name, count: 1) } }
Output
It will produce the following output −
Planet name is: Mercury No Planets like that: [No Planets]
The init! Failable Initializer
As we know we can create optional failable initializers with the help of init?, they return nil if the initialization process fails, otherwise, they will return an instance of the specified type. So to implicitly unwrapped optional instances swift provides a special type of initializer that is init!. It is used when the failure condition should never happen and if it occurs then the program will crash at run time. We can delegate from init? to init! or vice versa. We can override init? With init! or vice versa.
Example
Swift program to demonstrate init! failable initializers.
struct studrecord { let stname: String // init! initializer init!(stname: String) { if stname.isEmpty {return nil } self.stname = stname } } let stmark = studrecord(stname: "Swing") if let name = stmark { print("Student name: (name) is specified") } let blankname = studrecord(stname: "") if blankname == nil { print("Student name is left blank") }
Output
It will produce the following output −
Student name: studrecord(stname: "Swing") is specified Student name is left blank
Required Initializers
The required initializer in a class is the initializer that must be implemented by all the subclasses of that class where it is declared. To declare a required initializer using the required keyword, and all the subclass that implements the required initializer must use the required keyword. If we are overriding the required designed initializer, then we do not need to specify the override modifier before the initializer.
Syntax
Following is the syntax for the required initializer −
required init(parameterList) { // Statement }
Example
Swift program to demonstrate required initializers.
// Superclass class classA { // Required initializer required init() { let a = 10 print(a) } } // Subclass class classB: classA { // Required initializer required init() { let b = 30 print(b) } } // Instance of subclass and superclass let obj1 = classA() let obj2 = classB()
Output
It will produce the following output −
10 30 10
”;