Swift中Initialization的一些個人總結

godiscoder發表於2019-02-12

Swift

Initialization

1、初始化的兩種方式

1)這種方式有引數,在每次宣告新的例項的時候,你可以在定義的同時給它的temperature賦一個不同的值。

struct Fahrenheit {
    var temperature: Double
    init(temperature: Double) {
        self.temperature = temperature
    }
}
var f = Fahrenheit(temperature: 20)
print("The default temperature is (f.temperature)° Fahrenheit")複製程式碼

2)該方式每個生成的例項的temperature都有一個預設值。

struct Fahrenheit {
    var temperature = 32.0
}複製程式碼

2、帶有引數的構造器,呼叫的時候必須帶有引數列表。

struct Color {
    let red, green, blue: Double
    init(red: Double, green: Double, blue: Double) {
        self.red   = red
        self.green = green
        self.blue  = blue
    }
    init(white: Double) {
        red   = white
        green = white
        blue  = white
    }
}

let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let halfGray = Color(white: 0.5)
//該句會報錯
let veryGreen = Color(0.0, 1.0, 0.0)複製程式碼

3、你可以用_代替引數名

struct Celsius {
    var temperatureInCelsius: Double
    init(_ celsius: Double) {
        temperatureInCelsius = celsius
    }
}

let gelsius = Celsius(30)
print(gelsius.temperatureInCelsius)複製程式碼

4、你可以將在構造期間值不確定的屬性宣告為optional

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."複製程式碼

5、構造器代理

1)值型別(struct,enumeration)相對簡單,它們不支援繼承,只能呼叫自己的相關的構造器。

2)類的比較複雜,它們支援繼承。

struct Size {
    var width = 0.0, height = 0.0
}
struct Point {
    var x = 0.0, y = 0.0
}

struct Rect {
    var origin = Point()
    var size = Size()
    init() {}
    init(origin: Point, size: Size) {
        self.origin = origin
        self.size = size
    }
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}

let basicRect = Rect()
let originRect = Rect(origin: Point(x: 2.0, y: 2.0),size: Size(width: 5.0, height: 5.0))
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),size: Size(width: 3.0, height: 3.0))複製程式碼

6、Swift提供類的兩種構造器,指定構造器(designated initializers)和便利構造器(convenience initializers)
我們首要的應該使用designated initializers,每個類應至少有一個designated initializers,如果沒有必要的話,你可以不寫convenience initializers。
1)宣告designated initializers的語法

init(`parameters`) {
    `statements`
}複製程式碼

2)宣告convenience initializers的語法

convenience init(`parameters`) {
    `statements`
}複製程式碼

例子:

class Food {
    var name: String
    init(name: String) {
        self.name = name
    }
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}

let namedMeat = Food(name: "Bacon")
// namedMeat`s name is "Bacon"

let mysteryMeat = Food()
// mysteryMeat`s name is "[Unnamed]"複製程式碼

7、可失敗的構造器(Failable Initializer)

可失敗的構造器的關鍵字為init?

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"

//當你傳遞一個空字元創的時候,它會直接返回nil
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"複製程式碼

8、當你在init前面新增require關鍵字時,意味著該init方法必須在子類中實現。

class SomeClass {
    required init() {
        // initializer implementation goes here
    }
}

class SomeSubclass: SomeClass {
    required init() {
        // subclass implementation of the required initializer goes here
    }
}複製程式碼

9、使用閉包或者函式設定預設的屬性值

struct Chessboard {
    let boardColors: [Bool] = {
        var temporaryBoard = [Bool]()
        var isBlack = false
        for i in 1...8 {
            for j in 1...8 {
                temporaryBoard.append(isBlack)
                isBlack = !isBlack
            }
            isBlack = !isBlack
        }
        return temporaryBoard
    }()
    func squareIsBlackAt(row: Int, column: Int) -> Bool {
        return boardColors[(row * 8) + column]
    }
}

let board = Chessboard()
print(board.squareIsBlackAt(row: 0, column: 1))
// Prints "true"
print(board.squareIsBlackAt(row: 7, column: 7))
// Prints "false"複製程式碼

Tips:

  • 與Object-C中的構造器不同,Swift的構造器不需要有返回值。
  • 類和結構體在建立例項時,必須為所有儲存型屬性設定合適的初始值。儲存型屬性的值不能處於一個未知的狀態。
  • 對於類的例項,一個常量屬性只能在當前類的構造階段修改,不能由它的子類修改。
  • 構造器可以呼叫其他的構造器來執行例項的初始化,這個過程叫做構造器代理。
  • 如果你為某個值型別定義了一個自定義的構造器,你將無法訪問到預設構造器(如果是結構體,還將無法訪問逐 一成員構造器)。這種限制可以防止你為值型別增加了一個額外的且十分複雜的構造器之後,仍然有人錯誤的使用 自動生成的構造器。如果你想自定義的構造器和原始的都能使用,你可以將其寫在Extensions中。
  • 如果你使用閉包來初始化屬性,請記住在閉包執行時,例項的其它部分都還沒有初始化。這意味著你不能在閉包 裡訪問其它屬性,即使這些屬性有預設值。同樣,你也不能使用隱式的 self 屬性,或者呼叫任何例項方法。
    本文github地址

相關文章