Classes, structures and
enumerations once declared in Swift are initialized for preparing instance of a
class. Initial value is initialized for stored property and also for new
instances too the values are initialized to proceed further. The keyword to
create initialization function is carried out by 'init()' method. Swift
initializer differs from Objective-C that it does not return any values. Its
function is to check for initialization of newly created instances before its
processing. Swift also provides 'deinitialization' process for performing
memory management operations once the instances are deallocated.
Initializer Role for Stored Properties
Stored property have to initialize
the instances for its classes and structures before processing the instances.
Stored properties use initializer to assign and initialize values thereby
eradicating the need to call property observers. Initializer is used in stored
property.
• To create an initial value.
• To assign default property value within the property definition.
• To initialize an instance for a particular data type 'init()' is
used. No arguments are passed inside the init() function.
Syntax
init() {
//New
Instance initialization goes here
}
Example
struct rectangle {
var length: Double
var breadth: Double
init() {
length = 6
breadth = 12
}
}
var area = rectangle()
println("area of rectangle is \(area.length*area.breadth)")
Result:
area
of rectangle is 72.0
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. Area of rectangle is calculated and returned by calling the
rectangle function.
Setting Property Values by Default
Swift language provides Init()
function to initialize the stored property values. Also, the user has 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(). Setting property values by default enables the user
when inheritance is defined for classes or structures.
struct rectangle {
var length = 6
var breadth = 12
}
var area = rectangle()
println("area of rectangle is \(area.length*area.breadth)")
Result:
area
of rectangle is 72.0
Here instead of declaring length
and breadth in init() the values are initialized in declaration itself.
Parameters Initialization
In Swift language the user has the
provision to initialize parameters as part of the initializer's definition
using init().
struct Rectangle {
var length: Double
var breadth: Double
var area: Double
init(fromLength
length: Double, fromBreadth breadth: Double) {
self.length = length
self.breadth = breadth
area = length * breadth
}
init(fromLeng
leng: Double, fromBread bread: Double) {
self.length = leng
self.breadth = bread
area = leng * bread
}
}
let ar = Rectangle(fromLength: 6, fromBreadth: 12)
println("area is: \(ar.area)")
let are = Rectangle(fromLeng: 36, fromBread: 12)
println("area is: \(are.area)")
Result:
area
is: 72.0
area
is: 432.0
Local & External Parameters
Initialization parameters have both
local and global parameter names similar to that 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 initializer that they do not
identify which initializer are used to call which functions.
To overcome this, Swift introduces
an automatic external name for each and every parameter in init(). This
automatic external name is as equivalent as local name written before every
initialization parameter.
struct Days {
let sunday, monday, tuesday: Int
init(sunday: Int, monday: Int, tuesday: Int) {
self.sunday = sunday
self.monday = monday
self.tuesday = tuesday
}
init(daysofaweek: Int) {
sunday = daysofaweek
monday = daysofaweek
tuesday = daysofaweek
}
}
let week = Days(sunday: 1, monday: 2, tuesday: 3)
println("Days of a Week is: \(week.sunday)")
println("Days of a Week is: \(week.monday)")
println("Days of a Week is: \(week.tuesday)")
let weekdays = Days(daysofaweek: 4)
println("Days of a Week is: \(weekdays.sunday)")
println("Days of a Week is: \(weekdays.monday)")
println("Days of a Week is: \(weekdays.tuesday)")
Result:
Days
of a Week is: 1
Days
of a Week is: 2
Days
of a Week is: 3
Days
of a Week is: 4
Days
of a Week is: 4
Days
of a Week is: 4
Parameters without External Names
When an external name is not needed
for an initialize underscore '_' is used to override the default behavior.
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)
println("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
println("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
println("area is: \(recarea.length)")
Result:
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. When the
stored property is declared as 'optional' it automatically initializes the
value to be 'nil' during initialization itself.
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)
println("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
println("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
println("area is: \(recarea.length)")
Result:
area
is: Optional(180.0)
area
is: Optional(370.0)
area
is: Optional(110.0)
Modifying Constant Properties During
Initialization
Initialization also allows the user
to modify the value of constant property too. During initialization, class
property allows its class instances to be modified by the super class and not
by the subclass. Consider for example in the previous program 'length' is
declared as 'variable' in the main class. The below program variable 'length'
is modified as 'constant' variable.
struct Rectangle {
let 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)
println("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
println("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
println("area is: \(recarea.length)")
Result:
area
is: Optional(180.0)
area
is: Optional(370.0)
area
is: Optional(110.0)
Default Initializers
Default initializers provide a new
instance to all its declared properties of base class or structure with default
values.
class defaultexample {
var studname: String?
var stmark = 98
var pass = true
}
var result = defaultexample()
println("result is: \(result.studname)")
println("result is: \(result.stmark)")
println("result is: \(result.pass)")
Result:
result
is: nil
result
is: 98
result
is: true
The above program is defined with
class name as 'defaultexample'. Three member functions are initialized by
default as 'studname?' to store 'nil' values, 'stmark' as 98 and 'pass' as
Boolean value 'true'. Likewise the member values in the class can be
initialized as default before processing the class member types.
Memberwise Initializers for Structure Types
When the custom initializers are
not provided by the user, Structure types in Swift will automatically receive
the 'memberwise initializer'. Its main function is to initialize the new
structure instances with the default memberwise initialize and then the new
instance properties are passed to the memberwise initialize by name.
struct Rectangle {
var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)
println("Area of rectangle is: \(area.length)")
println("Area of rectangle is: \(area.breadth)")
Result:
Area
of rectangle is: 24.0
Area
of rectangle is: 32.0
Structures are initialized by
default for their membership functions during initialization for 'length' as
'100.0' and 'breadth' as '200.0'. But the values are overridden during the
processing of variables length and breadth as 24.0 and 32.0.
Initializer Delegation for Value Types
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.
struct Stmark {
var mark1 = 0.0, mark2 = 0.0
}
struct stdb {
var m1 = 0.0, m2 = 0.0
}
struct block {
var average = stdb()
var result = Stmark()
init() {}
init(average: stdb, result: Stmark) {
self.average = average
self.result = result
}
init(avg: stdb, result: Stmark) {
let tot = avg.m1 - (result.mark1 / 2)
let tot1 = avg.m2 - (result.mark2 / 2)
self.init(average: stdb(m1: tot, m2: tot1), result: result)
}
}
let set1 = block()
println("student result is: \(set1.average.m1, set1.average.m2) \(set1.result.mark1,
set1.result.mark2)")
let set2 = block(average: stdb(m1: 2.0, m2: 2.0),
result: Stmark(mark1: 5.0, mark2: 5.0))
println("student result is: \(set2.average.m1, set2.average.m2)
\(set2.result.mark1, set2.result.mark2)")
let set3 = block(avg: stdb(m1: 4.0, m2: 4.0),
result: Stmark(mark1: 3.0, mark2: 3.0))
println("student result is: \(set3.average.m1, set3.average.m2)
\(set3.result.mark1, set3.result.mark2)")
Result:
student
result is: (0.0, 0.0) (0.0, 0.0)
student
result is: (2.0, 2.0) (5.0, 5.0)
student
result is: (2.5, 2.5) (3.0, 3.0)
Rules for Initializer Delegation
Value Types
|
Class Types
|
Inheritance is not supported for
value types like structures and enumerations. Referring other initializers is
done through self.init.
|
Inheritance is supported. Checks
all stored property values are initialized.
|
Class Inheritance and Initialization
Class types have two kinds of
initializers to check whether defined stored properties receive an initial
value namely designated initializers and convenience initializers.
Designated Initializers and Convenience
Initializers
Designated Initializer
|
Convenience Initializer
|
Considered as primary initializes
for a class.
|
Considered as supporting
initialize for a class.
|
All class properties are
initialized and appropriate superclass initializer are called for further
initialization.
|
Designated initializer is called
with convenience initializer to create class instance for a specific use case
or input value type.
|
At least one designated
initializer is defined for every class.
|
No need to have convenience
initializers compulsory defined when the class does not require initializers.
|
Init(parameters) { statements }
|
convenience init(parameters) {
statements }
|
Program for Designated Initializers
class mainClass {
var no1 : Int // local
storage
init(no1 : Int) {
self.no1 = no1 //
initialization
}
}
class subClass : mainClass {
var no2 : Int // new
subclass storage
init(no1 : Int, no2 : Int) {
self.no2 = no2 //
initialization
super.init(no1:no1) // redirect
to superclass
}
}
let res = mainClass(no1: 10)
let print = subClass(no1: 10, no2: 20)
println("res is: \(res.no1)")
println("res is: \(print.no1)")
println("res is: \(print.no2)")
Result:
res
is: 10
res
is: 10
res
is: 20
Program for Convenience Initializers
class mainClass {
var no1 : Int // local
storage
init(no1 : Int) {
self.no1 = no1 //
initialization
}
}
class subClass : mainClass {
var no2 : Int
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)
}
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
println("res is: \(res.no1)")
println("res is: \(print.no1)")
println("res is: \(print.no2)")
Result:
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.
Inheritance is applicable to Super class initializers only to some extent which
will be discussed in Automatic Initializer Inheritance.
When the user needs to have
initializers defined in super class, subclass with initializers has to be
defined by the user as custom implementation. When overriding has to be taken
place by the sub class to the super class 'override' keyword has to be
declared.
class sides {
var corners = 4
var description: String {
return "\(corners)
sides"
}
}
let rectangle = sides()
println("Rectangle: \(rectangle.description)")
class pentagon: sides {
override init() {
super.init()
corners = 5
}
}
let bicycle = pentagon()
println("Pentagon: \(bicycle.description)")
Result:
Rectangle:
4 sides
Pentagon:
5 sides
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")
println("Planet name is: \(plName.name)")
let noplName = Planet()
println("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)
}
}
Result:
Planet
name is: Mercury
No
Planets like that: [No Planets]
Failable Initializer
The user has to be notified when
there are any initializer failures while defining a class, structure or
enumeration values. Initialization of variables sometimes become a failure one
due to –
• Invalid parameter values.
• Absence of required external source.
• Condition preventing initialization from succeeding.
To catch exceptions thrown by
initialization method, swift produces a flexible initialize called 'failable
initializer' to notify the user that something is left unnoticed while
initializing the structure, class or enumeration members. Keyword to catch the
failable initializer is 'init?'. Also, failable and non failable initializers
cannot be defined with same parameter types and names.
struct studrecord {
let stname: String
init?(stname: String) {
if stname.isEmpty {return nil }
self.stname = stname
}
}
let stmark = studrecord(stname: "Swing")
if let name = stmark {
println("Student
name is specified")
}
let blankname = studrecord(stname: "")
if blankname == nil {
println("Student
name is left blank")
}
Result:
Student
name is specified
Student
name is left blank
Failable Initializers for Enumerations
Swift language provides the
flexibility to have Failable initializers for enumerations too to notify the
user when the enumeration members are left from initializing values.
enum functions {
case a, b, c, d
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 {
println("With
In Block Two")
}
let badresult = functions(funct: "five")
if badresult == nil {
println("Block
Does Not Exist")
}
Result:
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, failable initializer in classes
will alert the failure only after the stored properties have been set to an
initial value.
class studrecord {
let studname: String!
init?(studname: String) {
self.studname = studname
if studname.isEmpty { return nil }
}
}
if let stname = studrecord(studname: "Failable
Initializers") {
println("Module
is \(stname.studname)")
}
Result:
Module
is Failable Initializers
Overriding a Failable Initializer
Like that of initialize the user
also has the provision to override a superclass failable initializer inside the
sub class. Super class failable initialize can also be overridden with in 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.
A non-failable initializer can
never delegate to a failable initializer.
The program given below describes
the failable and non-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")
println("Planet name is: \(plName.name)")
let noplName = Planet()
println("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)
}
}
Result:
Planet
name is: Mercury
No
Planets like that: [No Planets]
The init! Failable Initializer
Swift provides 'init?' to define an
optional instance failable initializer. To define an implicitly unwrapped
optional instance of the specific type 'init!' is specified.
struct studrecord {
let stname: String
init!(stname: String) {
if stname.isEmpty {return nil }
self.stname = stname
}
}
let stmark = studrecord(stname: "Swing")
if let name = stmark {
println("Student
name is specified")
}
let blankname = studrecord(stname: "")
if blankname == nil {
println("Student
name is left blank")
}
Result:
Student
name is specified
Student
name is left blank
Required Initializers
To declare each and every subclass
of the initialize 'required' keyword needs to be defined before the init()
function.
class classA {
required init() {
var a = 10
println(a)
}
}
class classB: classA {
required init() {
var b = 30
println(b)
}
}
let res = classA()
let print = classB()
Result:
10
30
10
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.