初始化(Initialization)
初始化概念:
类、结构体、枚举需要通过初始化对应的实例对象,来完成相应的功能。每一个实例初始化有相应的初始化方法。当初始化实例的时候就会执行对应的方法。与oc不同的是swift里面的初始化方法没有返回值。
Init方法实例
系统默认的初始化方法(init方法):
init() {
// perform some initialization here
} ```
#####如在结构体Fahrenheit 中定义一个无参数初始化方法:
struct Fahrenheit {
var temperature: Double
init() {
temperature = 32.0
}
}
var f = Fahrenheit()//在这里执行了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方法
一般来讲为了区分多个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)
####失败的初始化:
有时候会因为条件不满足可以执行可失败的初始化方法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表示初始化失败。如创建一个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//初始化失败执行这里
}
}
}
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可以自动执行失败的初始化并赋值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
}
} ```