初始化概念:
類甸祭、結構體、枚舉需要通過初始化對應的實例對象,來完成相應的功能灼捂。每一個實例初始化有相應的初始化方法离例。當初始化實例的時候就會執(zhí)行對應的方法。與oc不同的是swift里面的初始化方法沒有返回值悉稠。
Init方法實例
系統默認的初始化方法(init方法):
init() {
// perform some initialization here
} ```
#####如在結構體Fahrenheit 中定義一個無參數初始化方法:
struct Fahrenheit {
var temperature: Double
init() {
temperature = 32.0
}
}
var f = Fahrenheit()//在這里執(zhí)行了init方法
print("The default temperature is (f.temperature)° Fahrenheit")
// Prints "The default temperature is 32.0° Fahrenheit"```
定義多個init方法:
一個類宫蛆、結構體、枚舉里面可以定義多個init方法的猛,在Celsius 結構體中自定義內部參數分別為fahrenheit和kelvin 外部參數為fromFahrenheit 和fromKelvin 的init方法耀盗,需要不同的對象就調用不同的方法。
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
// boilingPointOfWater.temperatureInCelsius is 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// freezingPointOfWater.temperatureInCelsius is 0.0```
#####定義不需要外部參數名的init方法
一般來講為了區(qū)分多個init方法傳參的時候外部參數名是必須寫的卦尊,如果要省略需要在定義init的參數名前面加上_如下面的init(_ celsius: Double)
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
init(_ celsius: Double) {
temperatureInCelsius = celsius
}
}
let bodyTemperature = Celsius(37.0)
// bodyTemperature.temperatureInCelsius is 37.0```
定義一個可選參數:
如response在初始化的時候可以不用賦值則需要在類型后面加叛拷?說明。自動給它分配一個nil值岂却。
class SurveyQuestion {
var text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}
let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
cheeseQuestion.ask()
// Prints "Do you like cheese?"
cheeseQuestion.response = "Yes, I do like cheese."```
#####指定一個常量屬性
常量屬性由let關鍵字識別只能在聲明的class的init方法中修改忿薇,在其他地方以及子類的init方法中都不能修改
class SurveyQuestion {
let text: String//聲明一個text常量
var response: String?
init(text: String) {
self.text = text//只能在這里修改值
}
func ask() {
print(text)
}
}
let beetsQuestion = SurveyQuestion(text: "How about beets?")
beetsQuestion.ask()
// Prints "How about beets?"
beetsQuestion.response = "I also like beets. (But not with cheese.)"```
默認初始化:
類的默認初始化:
初始化一個ShoppingListItem 類的實例在沒有定義init方法時,ShoppingListItem (name的默認值是nil)由于每個屬性都有默認值就會把默認值分配給它的屬性
class ShoppingListItem {
var name: String?//因為類型后面加了躏哩?所以默認值是nil初始化可以不賦值
var quantity = 1
var purchased = false
}
var item = ShoppingListItem()```
#####結構體的默認初始化:
初始化一個Size結構體的實例通過它的屬性名對它的成員變量賦值署浩,即使沒有定義init方法但是系統會自動分配一個默認的init方法對width和height屬性賦值。
struct Size {
var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)```
重寫父類init方法:
定義一個Vehicle 類再定義一個Bicycle繼承它震庭,在init前面加override關鍵字Bicycle中重寫父類的init方法并且在init方法通過super.init()調用父類的init方法瑰抵。
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
let vehicle = Vehicle()
print("Vehicle: \(vehicle.description)")
// Vehicle: 0 wheel(s)
//定義Bicycle子類繼承Vehicle
class Bicycle: Vehicle {
override init() {
super.init()//調用父類的init方法
numberOfWheels = 2
}//重寫父類的init方法
}
let bicycle = Bicycle()
print("Bicycle: \(bicycle.description)")
// Bicycle: 2 wheel(s)```
接下來定義一個Food父類和RecipeIngredient繼承它,再定義一個ShoppingListItem類繼承RecipeIngredient
class Food {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[Unnamed]")
}
}```
聲明RecipeIngredient類繼承Food類器联,RecipeIngredient有三個初始化方法二汛。
class RecipeIngredient: Food {
var quantity: Int
init(name: String, quantity: Int) {
self.quantity = quantity
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, quantity: 1)
}
}
let oneMysteryItem = RecipeIngredient()//繼承父類的init方法
let oneBacon = RecipeIngredient(name: "Bacon")//重寫父類的 convenience init
let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6)//自己的init方法```
聲明ShoppingListItem類繼承RecipeIngredient 雖然ShoppingListItem沒有聲明init方法但是它繼承了RecipeIngredient 的三個init方法。
1.class ShoppingListItem: RecipeIngredient {
2.var purchased = false
3.var description: String {
4.var output = "\(quantity) x \(name)"
5.output += purchased ? " ?" : " ?"
6.return output
7.}
8.}
上面三個類的初始化方法關系如下:
![init方法關系圖](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/initializersExample03_2x.png)
####失敗的初始化:
有時候會因為條件不滿足可以執(zhí)行可失敗的初始化方法return nil并且要在init關鍵字后面加上問號拨拓,如下所示定義一個Animal 結構體肴颊,如果species屬性的值是空的話就會return nil。
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty { return nil }
self.species = species
}
}
let someCreature = Animal(species: "Giraffe")//初始化成功
//someCreature is of type Animal?, not Animal
if let giraffe = someCreature {
print("An animal was initialized with a species of (giraffe.species)")
}
// Prints "An animal was initialized with a species of Giraffe"
let anonymousCreature = Animal(species: "")//初始化化失敗
// anonymousCreature is of type Animal?, not Animal
if anonymousCreature == nil {
print("The anonymous creature could not be initialized")
}
// Prints "The anonymous creature could not be initialized"```
枚舉的失敗初始化
枚舉也有可能初始化失敗如果枚舉沒有有效的值傳入init方法中的話會和其他語言一樣有一個default選項return nil表示初始化失敗渣磷。如創(chuàng)建一個TemperatureUnit枚舉
enum TemperatureUnit {
case Kelvin, Celsius, Fahrenheit
init?(symbol: Character) {
switch symbol {
case "K":
self = .Kelvin
case "C":
self = .Celsius
case "F":
self = .Fahrenheit
default:
return nil//初始化失敗執(zhí)行這里
}
}
}
let fahrenheitUnit = TemperatureUnit(symbol: "F")
if fahrenheitUnit != nil {
print("This is a defined temperature unit, so initialization succeeded.")
}
// Prints "This is a defined temperature unit, so initialization succeeded."
let unknownUnit = TemperatureUnit(symbol: "X")
if unknownUnit == nil {
print("This is not a defined temperature unit, so initialization failed.")
}
// Prints "This is not a defined temperature unit, so initialization failed."```
枚舉的rawValues可以自動執(zhí)行失敗的初始化并賦值nil
enum TemperatureUnit: Character {
case Kelvin = "K", Celsius = "C", Fahrenheit = "F"
}
let fahrenheitUnit = TemperatureUnit(rawValue: "F")
if fahrenheitUnit != nil {
print("This is a defined temperature unit, so initialization succeeded.")
}
// Prints "This is a defined temperature unit, so initialization succeeded."
let unknownUnit = TemperatureUnit(rawValue: "X")
if unknownUnit == nil {
print("This is not a defined temperature unit, so initialization failed.")
}
// Prints "This is not a defined temperature unit, so initialization failed."```
失敗初始化的傳遞
父類初始化失敗也會導致子類初始化失敗
class Product {
let name: String
init?(name: String) {
if name.isEmpty { return nil }
self.name = name
}
}
class CartItem: Product {
let quantity: Int
init?(name: String, quantity: Int) {
if quantity < 1 { return nil }
self.quantity = quantity
super.init(name: name)//如果調用父類的init方法失敗也會導致失敗的初始化
}
}
//CartItem傳入的name是空值所以初始化失敗
if let oneUnnamed = CartItem(name: "", quantity: 1) {
print("Item: \(oneUnnamed.name), quantity: \(oneUnnamed.quantity)")
} else {
print("Unable to initialize one unnamed product")
}
// Prints "Unable to initialize one unnamed product"```
####Required子類必須實現的方法:
如果init方法前面有required 關鍵字意味著子類必須override重寫覆蓋實現這個方法或者子類也用required 等待下一個子類實現例如:
class SomeClass {
required init() {
// initializer implementation goes here
}
}
class SomeSubclass: SomeClass {
required init() {//等待它的子類用override實現父類的required init
// subclass implementation of the required initializer goes here
}
} ```