重庆时时彩组六单式 重庆时时彩犯法正规吗 重庆时时彩三码一胆 重庆时时彩平台手机版 山西福彩新时时彩 重庆时时彩走势dbshishicai88 重庆时时彩开奖视频怎么打不开了 如何破解重庆时时彩 360新时时彩删除 老时时彩20110601 重庆时时彩跨度介绍 重庆时时彩平台稳赚吗 360老时时彩怎么下注 新时时彩后2大小 重庆时时彩二星跨度走势图

轉載自泊學(boxueio.com)

我們繼續討論和IUO有關的話題。當IUO不是一個獨立的類型之后,所有與之有關的類型自動推導規則也發生了對應的變化。而這些變化,用一句話總結就是:你不能推導出一個不是類型的類型。其實,這和我們上一節說的,不能在別名和數組的定義中使用IUO的含義有些類似。

先來看下面這兩個例子:

var x: Int! let y = x // Int? func id<T>(_ value: T) -> T { return value }
type(of: id(x)) // Int? 

這里,盡管x的定義是Int!,但是無論是y的類型,還是id(x)的返回值的類型,都是Optional<Int>,也就是說,type inference推導不出來Int!這樣的的類型,因為它不是一個類型。并且,IUO可以自動解值的能力,也不會用在類型推導的過程里,繼續看這個例子:

func forcedResult() -> Int! { return x }
type(of: forcedResult) // () -> Optional<Int> func apply<T>(_ fn: () -> T) -> T { return fn() } // Error: Value of optional type 'Int?' not unwrapped let n: Int = apply(forcedResult)

可以看到,盡管forcedResult的定義里返回了Int!,但是Swift推導出來的類型是() -> Int?。正因為如此,我們也無法把apply的返回值賦值給一個Int類型的變量。根據類型自動推導的規則,apply不會返回Int!,而是Int?,自然也就無法自動對這個返回值進行unwrapped了。

應用在AnyObject屬性查詢時的改變

接下來,我們來看在查詢AnyObject屬性時的一個變化。為了了解這個過程,我們先定義兩個class:

class A: NSObject {} class C { @objc var n: A! = A()
}

然后,定義一個接受AnyObject參數的函數,并調用它:

func getProperty(object: AnyObject) {
    type(of: object.n) if let n = object.n {
        type(of: n)
    }
}

getProperty(object: C())

在4.2之前的Swift版本里,訪問AnyObject的屬性,得到的都是T!。例如,object.n得到的類型就是A!!。當我們通過if let n = object.nunwrap的時候,實際上只解掉了一層,因此,n的類型實際上是A!,只不過它有自動解值的特性,因此用起來像A罷了。

但到了4.2之后,情況就不是這樣了,AnyObject的屬性查詢,得到的結果都是T?,因此,object.n得到的類型是A??,這樣,我們就不能在if let n = object.n的作用域里,直接把n當作A的對象使用了,在這個作用域里,它的類型是A?。為了得到真正的A對象,我們得這樣:

func getProperty(object: AnyObject) {
    type(of: object.n) if let n: A = object.n {
        type(of: n)
    }
}

當我們在if let中強制約定了類型A之后,這里就會發生兩次unwrap,一次是unwrap AnyObject的查詢結果,一次是unwrap查詢結果自身,得到對象A。

異常處理相關的改變

和查詢AnyObject的屬性類似,另一個會帶來雙重optional的場景是使用try?調用可能發生異常的函數。如果這個函數本身返回optional類型,就會發生這種情形。我們來看個例子:

func fn() throws -> Int! { return 11 }

對于這個函數,當我們使用try? fn()調用的時候,在Swift 4.2之前,得到的返回值的類型是:Optional<ImplicitlyUnwrappedOptional<Int>>。也就是說,下面的代碼里,我們可以自動unwrap到Int值:

// This works before Swift 4.2 if let value = try? fn() { // unwrap outer optional let n: Int = value // unwrap innner IUO }

但在Swift 4.2版本之后,try? fn()的結果是Optional<Optional<Int>>。于是,上面的代碼就無法通過編譯了,內層的optional無法自動unwrap。為了讓它恢復編譯,我們得這樣:

if let value: Int = try? fn() { let n: Int = value
}

這樣,在if let語句中,借助type inference,就會完成兩次unwrap,我們就可以得到包含在其中的Int了。

switch語句中的類型匹配

我們要介紹的最后一個和類型推導有關的改動,是switch語句中的匹配。來看下面這個例子:

func switchDemo(_ input: String!) -> String { switch input { case let output: return output
    }
}

在Swift 4.2之前,output的類型是String!,因此我們可以直接返回ouput,自動得到其封裝的字符串作為返回值。但是,在Swift 4.2之后,output的類型會被推導為String?,因此,上面的代碼會報錯,提示我們無法自動把一個String?變成String。對此,我們有兩種解決方法。

第一種,就是在匹配的結果里,手工unwrap到String:

// In Swift 4.2 and later func switchDemo(_ input: String!) -> String { switch input { case let output: return output!
    }
}

第二種,就是我們明確去匹配optional非nil的情況:

func switchDemo(_ input: String!) -> String { switch input { case let output?: return output default: return "nil" }
}

相比前者,這種方法更為安全。

返回
頂部
重庆时时彩平台投注图
重庆时时彩组六单式 重庆时时彩犯法正规吗 重庆时时彩三码一胆 重庆时时彩平台手机版 山西福彩新时时彩 重庆时时彩走势dbshishicai88 重庆时时彩开奖视频怎么打不开了 如何破解重庆时时彩 360新时时彩删除 老时时彩20110601 重庆时时彩跨度介绍 重庆时时彩平台稳赚吗 360老时时彩怎么下注 新时时彩后2大小 重庆时时彩二星跨度走势图
连云港卖什么好赚钱 努力赚钱为什么 深海捕鱼可以提现的 捕鱼大师现金官方下载 腾讯分分彩玩法和倍率 美国赚钱游戏排行 nba投注网 阳泉煤业股票分析 足球任选9场奖金