swift学习笔记

初始化(Initialization)

2016-05-07  本文已影响30人  成功的失败者

初始化概念:

类、结构体、枚举需要通过初始化对应的实例对象,来完成相应的功能。每一个实例初始化有相应的初始化方法。当初始化实例的时候就会执行对应的方法。与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
}
} ```

上一篇下一篇

猜你喜欢

热点阅读