實例的初始化是準備一個類、結構體或枚舉的實例以便使用的過程。初始化包括設置一個實例存儲屬性的初始值,以及其他相關設置。
一個類、結構體或枚舉能定義一個初始化方法來設置它的特性,用來確保它的所有屬性都是有效的初始值。
通過調用類、結構或枚舉提供的初始化方法可以執行實例的初始化過程。
> 構造初始化類、結構體和枚舉的初始化方法所使用到的關鍵字是init。
## 初始化
### 初始化結構體
下面我們定義一個結構體Size,并添加兩個屬性wdith和height。
~~~
struct Size {
/// 寬
var width = 0.0
/// 高
var height = 0.0
}
~~~
使用結構體自帶的初始化方法實例化結構體:
~~~
// 默認初始化,使用的是init()構造方法
var size = Size()
// 結構體自帶根據成員初始化結構體的功能
size = Size(width: 10, height: 10)
~~~
接下來我們使用自定義的初始化功能初始化結構體,這里我們創建一個結構體Point,并添加兩個屬性x、y以及相關初始化方法。
~~~
struct Point {
var x = 0.0, y = 0.0
// MARK: 默認初始化
init() {
}
// MARK: 通過成員初始化結構體
init(x:Double, y:Double) {
self.x = x
self.y = y
}
}
// 自定義初始化
var point = Point() // 調用inin()方法
point = Point(x: 10, y: 10) // 調用init(x: Double, y:Double)方法
~~~
這就是仿照系統自帶的方法實現。但是當你在結構體自定義初始化方法時,則無法在外部使用系統自帶的初始化方法。
### 初始化枚舉
枚舉和結構體一樣也有一些系統自帶的初始化方法,和結構體不同的是,你在枚舉中自定義方法后,還是可以使用系統自帶的初始化方法。下面我們以一個CompassPoint枚舉舉例,它的內部是String類型。
~~~
enum CompassPoint:String {
case North, South, East, West
init(symbol: String) {
switch symbol {
case "North":
self = .North
case "South":
self = .South
case "East":
self = .East
default:
self = .West
}
}
}
// 直接取值
var compassPoint = CompassPoint.West
// 通過原始值初始化
compassPoint = CompassPoint(rawValue: "North")!
// 通過自定義的初始化方法
compassPoint = CompassPoint(symbol: "North")
~~~
在這里為大家介紹了三種初始化方法:直接取值、通過原始值和通過自定義的方法獲取枚舉。
### 初始化類
在Swift中,類是一個特殊的類型,它是引用類型,并且可繼承。這里定義兩個類:基類BaseClass和子類SubClass。
~~~
class BaseClass {
var name: String? // 可選屬性類型,可能為String或nil
init() {
print("Food:init()")
}
convenience init(name: String) {
self.init()
self.name = name
}
// MARK: - 省略外部參數
convenience init(_ subName: String) {
self.init(name: subName)
}
}
~~~
### 子類調用父類初始化方法
在子類的初始化方法中想調用父類的初始化方法,只需使用關鍵字super。
~~~
class SubClass: BaseClass {
override init() {
super.init() // 實現父類的init()方法
}
}
~~~
### 默認初始化
類和結構體一樣也有默認初始化,不同的是它只有一個默認初始化方法。
~~~
var user = SubClass()
~~~
### 自定義初始化
有的時候我們希望定制一些初始化方法方便外部調用,這里我們定制了初始化name的方法`init(name: String)`。
正如大家看見的在這個方法中我們使用了關鍵字convenience。convenience的作用就是當我們在一個初始化方法體內想調用另一個初始化方法體,則需要在func前加convenience。如我們在`init(name: String)`中使用了初始化方法`self.init()`
調用如下:
~~~
// 通過屬性初始化
user = SubClass(name: "陽君")
~~~
### 省略外部參數
在外部使用自定義的初始化方法時,需要使用參數名,如果你不想使用參數名,也可以在初始化的方法中參數名前加`_`,如
~~~
convenience init(_ subName: String) {
self.init(name: subName)
}
// 使用init(_ name: String)初始化
user = SubClass("陽君")
~~~
## 初始化失敗
在開發過程中,外部使用初始化方法時,由于傳入的參數不符合規范,我們需要返回nil,也就是初始化失敗。類、枚舉和結構體都可以初始化失敗。構造可返回nil的初始化方法很簡單,只需要在nil后添加“?”。
### 結構體初始化失敗
~~~
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty { return nil }
self.species = species
}
}
let someCreature = Animal(species: "Giraffe")
// 運用可選鏈判斷
if let giraffe = someCreature {
print("\(giraffe.species)") // Giraffe
}
~~~
使用Animal的init?(species: String)方法可能返回nil,也就是說someCreature為Animal或nil,接下來我們用了可選鏈的判斷方式。當giraff不為nil時輸出species屬性。
### 初始化枚舉失敗
~~~
enum TemperatureUnit:Character {
case Kelvin = "K", Celsius = "C", Fahrenheit = "F"
init?(symbol: Character) {
switch symbol {
case "K":
self = .Kelvin
case "C":
self = .Celsius
case "F":
self = .Fahrenheit
default:
return nil
}
}
}
// 通過自定義方法初始化
var unit = TemperatureUnit(symbol: "F")
print(unit) // Fahrenheit
unit = TemperatureUnit(symbol: "X")
print(unit) // nil
// 通過原始值初始化
unit = TemperatureUnit(rawValue: "F")
print(unit) // Fahrenheit
unit = TemperatureUnit(rawValue: "X")
print(unit) // nil
~~~
使用枚舉初始化失敗有兩種方式:一種是自定義的可返回nil方法;一種是使用原始值獲取枚舉。
### 類初始化失敗
~~~
class Product {
var name: String?
init() {}
init?(name: String) {
self.name = name
if name.isEmpty {
return nil
}
}
}
// 可選鏈操作,當bowTie為真時,執行內部代碼
if let qq = Product(name: "937447974") {
print(qq.name) // 937447974
}
~~~
## 必須初始化
有的時候我們會碰到這樣的場景,如父類提供了初始化方法,當子類繼承時,希望子類也強制性的初始化這個方法。這里就用到了關鍵字required。
~~~
class SomeClass {
required init() {
// required:子類要調用此方法,必須繼承實現
}
}
class SomeSubclass: SomeClass {
required init() {
}
init(required:String) {
super.init()
// 這里調用父類的init()方法,當前類必須實現init()方法
}
}
~~~
## 使用閉包或函數設置默認屬性
在類中我們可以設置屬性的默認值,我們還可以通過閉包或函數設置屬性的默認值。
~~~
class SomeClass {
let someProperty: String = {
// create a default value for someProperty inside this closure
// someValue must be of the same type as SomeType
return "someValue"
}()
}
let c = SomeClass()
print(c.someProperty) // someValue
~~~
## 其他
### 參考資料
[The Swift Programming Language (Swift 2.1)](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html)
### 文檔修改記錄
| 時間 | 描述 |
|-----|-----|
| 2015-10-31 | 根據 [The Swift Programming Language (Swift 2.1)](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html)中的Initialization總結 |
版權所有:[http://blog.csdn.net/y550918116j](http://blog.csdn.net/y550918116j)
- 前言
- Swift函數
- Swift閉包(Closures)
- Swift枚舉(Enumerations)
- Swift類和結構體(Classes and Structures)
- Swift屬性(Properties)
- Swift方法(Methods)
- Swift下標(Subscripts)
- Swift繼承(Inheritance)
- Swift初始化(Initialization)
- Swift銷毀(Deinitialization)
- Swift可選鏈(Optional Chaining)
- Swift錯誤處理(Error Handling)
- Swift類型選擇(Type Casting)
- Swift協議(Protocols)
- Swift訪問控制(Access Control)
- Swift高級運算符(Advanced Operators)