Swift建構函式(Initializer)

儲存屬性的初始化程式角色

• 建立初始值。
• 在屬性定義中指定預設屬性值。
• 要初始化特定資料型別的範例，請使用`init()``init()`函式內沒有傳遞引數。

``````init() {
//New Instance initialization goes here
}
``````

``````struct rectangle {
var length: Double
init() {
length = 6
}
}

var area = rectangle()
``````

``````area of rectangle is 72.0
``````

預設設定屬性值

Swift 4語言提供`Init()`函式來初始化儲存的屬性值。 此外，使用者可以在宣告類或結構成員時預設初始化屬性值。 當屬性在整個程式中單獨使用相同的值時，可以單獨在宣告部分宣告它，而不用在`init()`中初始化它。 預設情況下，設定屬性值會在為類或結構定義繼承時啟用。

``````struct rectangle {
var length = 6
}

var area = rectangle()
``````

``````area of rectangle is 72
``````

引數初始化

``````struct Rectangle {
var length: Double
var area: Double

self.length = length
}
self.length = leng
}
}

let ar = Rectangle(fromLength: 6, fromBreadth: 12)
print("area is: \(ar.area)")

let are = Rectangle(fromLeng: 36, fromBread: 12)
print("area is: \(are.area)")
``````

``````area is: 72.0
area is: 432.0
``````

區域性和外部引數

``````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)
print("Days of a Week is: \(week.sunday)")
print("Days of a Week is: \(week.monday)")
print("Days of a Week is: \(week.tuesday)")

let weekdays = Days(daysofaweek: 4)
print("Days of a Week is: \(weekdays.sunday)")
print("Days of a Week is: \(weekdays.monday)")
print("Days of a Week is: \(weekdays.tuesday)")
``````

``````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
``````

無外部名稱的引數

``````struct Rectangle {
var length: Double

}
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)")
``````

``````area is: 180.0
area is: 370.0
area is: 110.0
``````

optional屬性型別

``````struct Rectangle {
var length: Double?

}
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)")
``````

``````area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)
``````

初始化期間修改常數屬性

``````struct Rectangle {
let length: Double?

}
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)")
``````

``````area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)
``````

預設初始化器

``````class defaultexample {
var studname: String?
var stmark = 98
var pass = true
}
var result = defaultexample()

print("result is: \(result.studname)")
print("result is: \(result.stmark)")
print("result is: \(result.pass)")
``````

``````result is: nil
result is: 98
result is: true
``````

結構型別的成員初始化器

``````struct Rectangle {
var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)

print("Area of rectangle is: \(area.length)")
``````

``````Area of rectangle is: 24.0
Area of rectangle is: 32.0
``````

值型別的初始化程式委派

``````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()
print("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))
print("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))
print("student result is: \(set3.average.m1, set3.average.m2)
\(set3.result.mark1, set3.result.mark2)")
``````

``````(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)
``````

類繼承和初始化

`Init(parameters) { statements }` `convenience init(parameters) { statements }`

``````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)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
``````

``````res is: 10
res is: 10
res is: 20
``````

``````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)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
``````

``````res is: 20
res is: 30
res is: 50
``````

初始化器繼承和覆蓋

``````class sides {
var corners = 4
var description: String {
return "\(corners) sides"
}
}

let rectangle = sides()
print("Rectangle: \(rectangle.description)")

class pentagon: sides {
override init() {
super.init()
corners = 5
}
}

let bicycle = pentagon()
print("Pentagon: \(bicycle.description)")
``````

``````Rectangle: 4 sides
Pentagon: 5 sides
``````

``````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)
}
}
``````

``````Planet name is: Mercury
No Planets like that: [No Planets]
``````

可失敗的初始化程式

• 引數值無效。
• 缺少必需的外部來源。
• 防止初始化成功的條件。

``````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 {
print("Student name is specified")
}
let blankname = studrecord(stname: "")

if blankname == nil {
print("Student name is left blank")
}
``````

``````Student name is specified
Student name is left blank
``````

列舉的可失敗初始化程式

Swift 4語言提供了列舉的`Failable`初始值設定器，以便在列舉成員離開初始化值時通知使用者。

``````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 {
print("With In Block Two")
}

print("Block Does Not Exist")
}
``````

``````With In Block Two
Block Does Not Exist
``````

類的可失敗初始化程式

``````class studrecord {
let studname: String!
init?(studname: String) {
self.studname = studname
if studname.isEmpty { return nil }
}
}

if let stname = studrecord(studname: "Failable Initializers") {
print("Module is \(stname.studname)")
}
``````

``````Module is Optional("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)
}
}
``````

``````Planet name is: Mercury
No Planets like that: [No Planets]
``````

init!可失敗初始化程式

Swift 4提供`init?` 定義一個可選的範例`failable`初始化程式。 定義特定型別`init!`的隱式解包的可選範例。

``````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 {
print("Student name is specified")
}

let blankname = studrecord(stname: "")

if blankname == nil {
print("Student name is left blank")
}
``````

``````Student name is specified
Student name is left blank
``````

必需的初始化程式

``````class classA {
required init() {
var a = 10
print(a)
}
}

class classB: classA {
required init() {
var b = 30
print(b)
}
}

let res = classA()
let print = classB()
``````

``````10
30
10
``````