Swift4 基礎(chǔ)部分: Initialization

本文是學(xué)習(xí)《The Swift Programming Language》整理的相關(guān)隨筆日裙,基本的語法不作介紹,主要介紹Swift中的一些特性或者與OC差異點(diǎn)麦牺。

系列文章:

初始化器(Initializers)

  • 直接查看基本的使用例子:

例子:

struct Fahrenheit{
    var temperature:Double;
    init() {
        temperature = 32.0;
    }
}

var f = Fahrenheit();
print("The default temperature is \(f.temperature)° Fahrenheit")

執(zhí)行結(jié)果:

The default temperature is 32.0° Fahrenheit

自定義初始化(Customizing Initialization)

例子:

    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)
print("The default temperature is \(boilingPointOfWater.temperatureInCelsius)° Fahrenheit")
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
print("The default temperature is \(freezingPointOfWater.temperatureInCelsius)° Fahrenheit")

執(zhí)行結(jié)果:

The default temperature is 100.0° Fahrenheit
The default temperature is 0.0° Fahrenheit

參數(shù)名稱和參數(shù)標(biāo)簽(Parameter Names and Argument Labels)

例子:

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)
print("magenta red:\(magenta.red) green:\(magenta.green) blue:\(magenta.blue)");
print("halfGray red:\(halfGray.red) green:\(halfGray.green) blue:\(halfGray.blue)");

執(zhí)行結(jié)果:

magenta red:1.0 green:0.0 blue:1.0
halfGray red:0.5 green:0.5 blue:0.5

不需要參數(shù)標(biāo)簽的初始化器(Initializer Parameters Without Argument Labels)

直接看例子:

struct Celsius{
    var temperatureInCelsius:Double;
    init(fromFahrenheit fahrenheit:Double){
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8;
    }
    
    init(fromKelvin kelvin:Double){
        temperatureInCelsius = kelvin - 273.15;
    }
    
    // 此處就是具體的體現(xiàn)
    init(_ celsius:Double){
        temperatureInCelsius = celsius;
    }
}
let bodyTemperature = Celsius(37.0);
print(bodyTemperature.temperatureInCelsius);

執(zhí)行結(jié)果:

37.0

可選屬性類型(Optional Property Types)

If your custom type has a stored property that is 
logically allowed to have “no value”—perhaps because its 
value cannot be set during initialization, or because it 
is allowed to have “no value” at some later point—declare 
the property with an optional type. 
  • 如果你定制的類型是允許取值為空的存儲型屬性--不管是因?yàn)樗鼰o法在初始化時(shí)賦值钮蛛,還是因?yàn)樗梢栽谥竽硞€(gè)時(shí)間點(diǎn)可以賦值為空--你都需要將它定義為可選類型。
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()
cheeseQuestion.response = "Yes, I do like cheese."

執(zhí)行結(jié)果:

Do you like cheese?

構(gòu)造過程中常量屬性的修改(Assigning Constant Properties During Initialization)

  • 只要在構(gòu)造過程結(jié)束前常量的值能確定剖膳,你可以在構(gòu)造過程中的任意時(shí)間點(diǎn)修改常量屬性的值魏颓。
  • 對某個(gè)類實(shí)例來說,它的常量屬性只能在定義它的類的構(gòu)造過程中修改吱晒;不能在子類中修改甸饱。

例子:

class SurveyQuestion {
    let text: String
    var response: String?
    init(text: String) {
        self.text = text
    }
    func ask() {
        print(text)
    }
}

class DetailSurveyQuestion:SurveyQuestion{
    
    init(content content: String){
        self.text = content;
    }
}
let beetsQuestion = SurveyQuestion(text: "How about beets?")
beetsQuestion.ask()
// 輸出 "How about beets?"
beetsQuestion.response = "I also like beets. (But not with cheese.)"

執(zhí)行結(jié)果:編譯錯(cuò)誤驗(yàn)證上述結(jié)論2

Playground execution failed: error: MyPlayground.playground:900:19: error: cannot assign to property: 'text' is a 'let' constant
        self.text = content;
        ~~~~~~~~~ ^

去掉子類的實(shí)現(xiàn),執(zhí)行結(jié)果:

How about beets?

默認(rèn)構(gòu)造器(Default Initializers)

Swift provides a default initializer for any structure or 
class that provides default values for all of its 
properties and does not provide at least one initializer 
itself.
  • Swift 將為所有屬性已提供默認(rèn)值的且自身沒有定義任何構(gòu)造器的結(jié)構(gòu)體或基類仑濒,提供一個(gè)默認(rèn)的構(gòu)造器叹话。

例子:


class ShoppingListItem {
    var name: String?;
    var quantity = 1;
    var purchased = false;
}
var item = ShoppingListItem();

結(jié)構(gòu)體的逐一成員構(gòu)造器(Memberwise Initializers for Structure Types)

Structure types automatically receive a memberwise 
initializer if they do not define any of their own custom 
initializers. Unlike a default initializer, the structure 
receives a memberwise initializer even if it has stored 
properties that do not have default values.
  • 結(jié)構(gòu)體類型可以自動接收逐一成員構(gòu)造器,如果他們沒有定義任何的構(gòu)造器。

例子:

struct Size {
    var width = 0.0, height = 0.0;
}
let size = Size(width:2.0, height:2.0);
print("size \(size.width) \(size.height)");

執(zhí)行結(jié)果:

size 2.0 2.0

值類型的構(gòu)造器代理(Initializer Delegation for Value Types)

Initializers can call other initializers to perform part 
of an instance’s initialization. This process, known as 
initializer delegation, avoids duplicating code across 
multiple initializers. 
  • 構(gòu)造器可以通過調(diào)用其它構(gòu)造器來完成實(shí)例的部分構(gòu)造過程墩瞳。這一過程稱為構(gòu)造器代理驼壶,它能避免多個(gè)構(gòu)造器間的代碼重復(fù)。

例子:

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 originReact = Rect(origin:Point(x:2.0,y:2.0),size:Size(width:5.0,height:5.0));
print("point:\(originReact.origin) size:\(originReact.size)");

執(zhí)行結(jié)果:

point:Point(x: 2.0, y: 2.0) size:Size(width: 5.0, height: 5.0)

類的繼承與構(gòu)造過程(Class Inheritance and Initialization)

Swift defines two kinds of initializers for class types to 
help ensure all stored properties receive an initial 
value. These are known as designated initializers and 
convenience initializers.
  • Swift 提供了兩種類型的類構(gòu)造器來確保所有類實(shí)例中存儲型屬性都能獲得初始值喉酌,它們分別是指定構(gòu)造器和便利構(gòu)造器热凹。

指定構(gòu)造器和便利構(gòu)造器的語法(Syntax for Designated and Convenience Initializers)

指定構(gòu)造器語法:

init(parameters) {
    statements
}

便利構(gòu)造器語法:

convenience init(parameters) {
    statements
} 

類的構(gòu)造器代理(Initializer Delegation for Class Types)

基本規(guī)則:

Designated initializers must always delegate up.
Convenience initializers must always delegate across.
  • 指定構(gòu)造器必須總是向上代理泵喘。
  • 便利構(gòu)造器必須總是橫向代理。

構(gòu)造器的繼承與重載(Initializer Inheritance and Overriding)

When you write a subclass initializer that matches a 
superclass designated initializer, you are effectively 
providing an override of that designated initializer. 
Therefore, you must write the override modifier before the 
subclass’s initializer definition.
  • 可以在子類中通過關(guān)鍵字override重載父類的構(gòu)造器方法般妙。

例子:

class Vehicle {
    var numberOfWheels = 0;
    var description:String {
        return "\(numberOfWheels) wheel(s)";
    }
}

class Bicycle:Vehicle {
    override init() {
        super.init();
        numberOfWheels = 2;
    }
}

let bicycle = Bicycle();
print("Bicycle: \(bicycle.description)");

執(zhí)行結(jié)果:

Bicycle: 2 wheel(s)

指定構(gòu)造器和便利構(gòu)造器實(shí)戰(zhàn)(Designated and Convenience Initializers in Action)

直接看一下指定構(gòu)造器與便利構(gòu)造器的實(shí)際應(yīng)用的例子:

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

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);
    }
}

class ShoppingListItem: RecipeIngredient {
    var purchased = false;
    
    var description: String {
        var output = "\(quantity) x \(name)";
        output += purchased ? " ?" : " ?";
        return output;
    }
}

var breakfastList = [
    ShoppingListItem(),
    ShoppingListItem(name: "Bacon"),
    ShoppingListItem(name: "Eggs", quantity: 6),
];
breakfastList[0].name = "Orange juice";
breakfastList[0].purchased = true;
for item in breakfastList {
    print(item.description);
}

執(zhí)行結(jié)果:

1 x Orange juice ?
1 x Bacon ?
6 x Eggs ?

可失敗的構(gòu)造器(Failable Initializers)

It is sometimes useful to define a class, structure, or 
enumeration for which initialization can fail. This 
failure might be triggered by invalid initialization 
parameter values, the absence of a required external 
resource, or some other condition that prevents 
initialization from succeeding.
  • 如果一個(gè)類纪铺,結(jié)構(gòu)體或枚舉類型的對象,在構(gòu)造自身的過程中有可能失敗碟渺,則為其定義一個(gè)可失敗構(gòu)造器鲜锚,是非常有用的。這類錯(cuò)誤可能是參數(shù)或者確實(shí)外部資源等苫拍。

例子:

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("An animal was initialized with a species of \(giraffe.species)");
}

執(zhí)行結(jié)果:

An animal was initialized with a species of Giraffe

枚舉類型的可失敗構(gòu)造器(Failable Initializers for Enumerations)

例子:

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.")
}

執(zhí)行結(jié)果:

This is a defined temperature unit, so initialization succeeded.
This is not a defined temperature unit, so initialization failed.

帶原始值的枚舉類型的可失敗構(gòu)造器(Failable Initializers for Enumerations with Raw Values)

例子:

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.")
}

let unknownUnit = TemperatureUnit(rawValue: "X")
if unknownUnit == nil {
    print("This is not a defined temperature unit, so initialization failed.")
}

執(zhí)行結(jié)果:

This is a defined temperature unit, so initialization succeeded.
This is not a defined temperature unit, so initialization failed.

構(gòu)造失敗的傳遞(Propagation of Initialization Failure)

A failable initializer of a class, structure, or 
enumeration can delegate across to another failable 
initializer from the same class, structure, or 
enumeration. Similarly, a subclass failable initializer 
can delegate up to a superclass failable initializer.
  • 可失敗構(gòu)造器在同一類芜繁,結(jié)構(gòu)體和枚舉中橫向代理其他的可失敗構(gòu)造器。類似的怯疤,子類的可失敗構(gòu)造器也能向上代理基類的可失敗構(gòu)造器浆洗。

例子:

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);
    }
}

if let twoSocks = CartItem(name: "sock", quantity: 2) {
    print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)");
}

if let zeroShirts = CartItem(name: "shirt", quantity: 0) {
    print("Item: \(zeroShirts.name), quantity: \(zeroShirts.quantity)");
} else {
    print("Unable to initialize zero shirts");
}

if let oneUnnamed = CartItem(name: "", quantity: 1) {
    print("Item: \(oneUnnamed.name), quantity: \(oneUnnamed.quantity)");
} else {
    print("Unable to initialize one unnamed product");
}

執(zhí)行結(jié)果:

Item: sock, quantity: 2
Unable to initialize zero shirts
Unable to initialize one unnamed product

覆寫父類的可失敗的構(gòu)造器(Overriding a Failable Initializer)

You can override a superclass failable initializer in a subclass, just like any other initializer.
  • 就如同其它構(gòu)造器一樣,你也可以用子類的可失敗構(gòu)造器覆蓋基類的可失敗構(gòu)造器集峦。

例子:

class Document {
    var name: String?;

    init() {};

    init?(name: String) {
        if name.isEmpty { return nil }
        self.name = name
    }
}

class AutomaticallyNamedDocument: Document {
    override init() {
        super.init();
        self.name = "[Untitled]";
    }
    override init(name: String) {
        super.init();
        if name.isEmpty {
            self.name = "[Untitled]";
        } else {
            self.name = name;
        }
    }
}

必須存在的構(gòu)造器(Required Initializers)

Write the required modifier before the definition of a 
class initializer to indicate that every subclass of the 
class must implement that initializer: 

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

class SomeSubclass: SomeClass {
    required init() {
        // subclass implementation of the required initializer goes here
    }
}

通過閉包和函數(shù)來設(shè)置屬性的默認(rèn)值(Setting a Default Property Value with a Closure or Function)

If a stored property’s default value requires some 
customization or setup, you can use a closure or global 
function to provide a customized default value for that 
property. 
  • 如果某個(gè)存儲型屬性的默認(rèn)值需要特別的定制或準(zhǔn)備伏社,你就可以使用閉包或全局函數(shù)來為其屬性提供定制的默認(rèn)值。

例子:


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));
print(board.squareIsBlackAt(row: 7, column: 7));

執(zhí)行結(jié)果:

true
true
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末塔淤,一起剝皮案震驚了整個(gè)濱河市摘昌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌高蜂,老刑警劉巖聪黎,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異备恤,居然都是意外死亡稿饰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門露泊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來喉镰,“玉大人,你說我怎么就攤上這事惭笑÷履罚” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵沉噩,是天一觀的道長捺宗。 經(jīng)常有香客問我,道長川蒙,這世上最難降的妖魔是什么蚜厉? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮派歌,結(jié)果婚禮上弯囊,老公的妹妹穿的比我還像新娘痰哨。我一直安慰自己匾嘱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布早抠。 她就那樣靜靜地躺著霎烙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蕊连。 梳的紋絲不亂的頭發(fā)上悬垃,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天,我揣著相機(jī)與錄音甘苍,去河邊找鬼尝蠕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛载庭,可吹牛的內(nèi)容都是我干的看彼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼囚聚,長吁一口氣:“原來是場噩夢啊……” “哼靖榕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起顽铸,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤茁计,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后谓松,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體星压,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年鬼譬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了娜膘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拧簸,死狀恐怖劲绪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盆赤,我是刑警寧澤贾富,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站牺六,受9級特大地震影響颤枪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜淑际,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一畏纲、第九天 我趴在偏房一處隱蔽的房頂上張望扇住。 院中可真熱鬧,春花似錦盗胀、人聲如沸艘蹋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽女阀。三九已至,卻和暖如春屑迂,著一層夾襖步出監(jiān)牢的瞬間浸策,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工惹盼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留庸汗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓手报,卻偏偏與公主長得像蚯舱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子昧诱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容