[Swift]Swift中的init方法
1.說明
- Struct中的init的機(jī)制和class的基本類似查排,不同點我在 中也已經(jīng)說明
- 本文以Class的init方法為例
2.designated init
class 中所有的成員變量在對象創(chuàng)建時必須有一個初始值
所以下面這種形式無法通過編譯
class Point2D{
var x : Double
var y : Double
}
修改方式1:為成員變量加上一個默認(rèn)值
class Point2D{
var x:Double = 1.0
var y:Double = 1.0
}
這樣就有一個默認(rèn)的無參的init方法
let p = Point2D()
//修改方式2:為class加上一個designated init
方法
即在此方法中將所有的沒有默認(rèn)值的員變量初始化
class Point2D2{
var x:Double
var y:Double
init(x:Double,y:Double){
self.x = x
self.y = y
}
}
這樣就有一個有兩個參數(shù)的init方法瘸恼,而默認(rèn)的無參的init方法,已經(jīng)沒有了
// let p2 = Point2D2() //錯誤
let p21 = Point2D2(x:1,y:1)
其實這樣要把所有沒有默認(rèn)值的成員變量初始化的init方法跟我博客中 全能初始化方法 這章提到的全能初始化方法比較類似
3.convenience init 方法
除了有designated init方法,一個類中還可以設(shè)定convenience init方法來方便初始化
比如
class Point2D3{
var x:Double
var y:Double
init(x:Double,y:Double){
self.x = x
self.y = y
}
convenience init(xStr:String,yStr:String){
let x = Double(xStr)
let y = Double(yStr)
self.init(x:x!,y:y!)
}
convenience init(xy:(Double,Double)){
let x = xy.0
let y = xy.1
self.init(x:x,y:y)
}
}
這樣我們就有多種方式創(chuàng)建這個類的對象
let p3 = Point2D3(x:1,y:1)
let p31 = Point2D3(xStr: "1",yStr: "1")
let p32 = Point2D3(xy:(1,1))
但是通過字符串創(chuàng)建很可能會出現(xiàn)問題
//let p34 = Point2D3(xStr: "aaa",yStr: "1")
//error :fatal error: unexpectedly found nil while unwrapping an Optional value
4.failable init方法错邦,即有允許初始化失敗時返回nil
class Point2D4{
var x:Double
var y:Double
init(x:Double,y:Double){
self.x = x
self.y = y
}
convenience init?(xStr:String,yStr:String){
let x = Double(xStr)
let y = Double(yStr)
if x == nil || y == nil{
return nil
}
self.init(x:x!,y:y!)
}
}
failable init 還可以是designated init方法
以前返回nil的語句應(yīng)該放在成員變量初始化之后,經(jīng)測試敦第,現(xiàn)在沒有了這個限制
class Point2D5{
var x:Double
var y:Double
// init?(x:Double,y:Double){
// self.x = x
// self.y = y
// if(x < 0 || y < 0 ){
// return nil
// }
// }
init?(x:Double,y:Double){
if(x < 0 || y < 0 ){
return nil
}
self.x = x
self.y = y
}
}
這樣我們創(chuàng)建失敗后就不會報錯徽惋,會是一個nil,
但是請注意铅歼,這樣創(chuàng)建出來的對象是一個optional對象
let p4 = Point2D4(xStr: "aaa",yStr: "1")
p4 //nil
let p41 = Point2D4(xStr: "1",yStr: "1")
p41 //1,1
let p5 = Point2D5(x:1,y:-1)
p4.dynamicType //Optional<Point2D4>.Type
p5.dynamicType //Optional<Point2D5>.Type
5.初始化自身屬性時需要self作為參數(shù)傳遞給屬性的初始化參數(shù)
class City{
var country : Country
init(country:Country){
self.country = country;
}
}
class Country {
var capital : City
init(){
//編譯器認(rèn)為本對象的capital還沒初始化完,不能使用self
//而初始化capital又必須使用self
//每個國家必須有一個首都,captial屬性也不能設(shè)置為optional
//所以需要把capital設(shè)置為implicitly unwrapped Optional换可,這樣椎椰,編譯器就認(rèn)為capital已經(jīng)被初始化過,初始化值為nil
self.capital = City(country:self) //報錯
}
}
所以Country類應(yīng)該修改為這樣
class Country {
var capital : City!
init()
self.capital = City(country:self) //正確
}
}
6.屬性是一個使用self變量的closure
class HTMLElement{
var text:String
init(text:String){
self.text=text
}
var asHTML : Void -> String = {
return "<text>\(self.text)</text>"
} //error: use of unresolved identifier 'self'
}
編譯器無法識別closure中的self屬性沾鳄,所以這個時候應(yīng)該使用lazy property
class HTMLElement{
var text:String
init(text:String){
self.text=text
}
lazy var asHTML : Void -> String = {
return "<text>\(self.text)</text>"
}
}
這樣就不會報錯,但是這樣還是會有循環(huán)引用的問題慨飘,關(guān)于這個問題,我在第24篇中有詳細(xì)描述