初始化(Initialization)

初始化概念:

類甸祭、結構體、枚舉需要通過初始化對應的實例對象,來完成相應的功能灼捂。每一個實例初始化有相應的初始化方法离例。當初始化實例的時候就會執(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
}
} ```

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末婿着,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子醋界,更是在濱河造成了極大的恐慌竟宋,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件形纺,死亡現場離奇詭異丘侠,居然都是意外死亡,警方通過查閱死者的電腦和手機逐样,發(fā)現死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門蜗字,熙熙樓的掌柜王于貴愁眉苦臉地迎上來打肝,“玉大人,你說我怎么就攤上這事挪捕〈炙螅” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵级零,是天一觀的道長断医。 經常有香客問我,道長妄讯,這世上最難降的妖魔是什么孩锡? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮亥贸,結果婚禮上躬窜,老公的妹妹穿的比我還像新娘。我一直安慰自己炕置,他們只是感情好荣挨,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著朴摊,像睡著了一般默垄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上甚纲,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天口锭,我揣著相機與錄音,去河邊找鬼介杆。 笑死鹃操,一個胖子當著我的面吹牛,可吹牛的內容都是我干的春哨。 我是一名探鬼主播荆隘,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼赴背!你這毒婦竟也來了椰拒?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤凰荚,失蹤者是張志新(化名)和其女友劉穎燃观,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體便瑟,經...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡缆毁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了胳徽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片积锅。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖养盗,靈堂內的尸體忽然破棺而出缚陷,到底是詐尸還是另有隱情,我是刑警寧澤往核,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布箫爷,位于F島的核電站,受9級特大地震影響聂儒,放射性物質發(fā)生泄漏虎锚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一衩婚、第九天 我趴在偏房一處隱蔽的房頂上張望窜护。 院中可真熱鬧,春花似錦非春、人聲如沸柱徙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽护侮。三九已至,卻和暖如春储耐,著一層夾襖步出監(jiān)牢的瞬間羊初,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工什湘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留长赞,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓禽炬,卻偏偏與公主長得像涧卵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子腹尖,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容