title: “Why coding like This —— Optional 揭祕”
date: 2015-08-12 00:21:16
categories: “why coding like this”
tags: [swift進階]
Optional 揭祕
Topic 1:
請簡單寫出可選類型的聲明方式,以及幾種解包形式。
Example:
/// 幾種聲明方式
var optionalValue : Optional<Int> //完整聲明 注意<>中的都是類型
var optionalValue2 : Int? //顯示聲明
var optionalValue3 : Int! //隱式聲明
/// 幾種解包
/// 演示值
var someOptional:Int? = 3 //初始值爲3
/// 1.通過判斷是否等於nil 這裏並未解包 只能保證安全性
if someOptional != nil{
println("value is \(someOptional!)")
}
/// 2.if-let綁定
if let value = someOptional{
println("value is \(value)")
}
/// 3.??解包
println("value is \(someOptional ?? 2)")
/// 4.swift2.0新的匹配模式 但是要在xcode7環境
//新增使用enumeration匹配 也就是枚舉匹配方式
if case .Some(let x) = someOptional{
println("someOptional value is \(x)") //如果爲nil 情況 可不會輸出東西 因爲匹配的是Some!
}
//新增使用可選模式匹配
if case let x? = someOptional{
println("someOptional value is \(x)") //不需要對x進行解包之類的東東
}
其中第四種方法僅在xcode7環境 以及swift2.0語法下支持。更多語法改動請點擊這裏。關於可選類型解包請點擊這裏。 更多基礎語法請查看官方文檔。
why coding like this?
命題一
給定某個變量,在程序運行的時候存在兩種情況:不存在任何值;存在值,等於x。設計一個類型來封裝這種情況。
思路
其實談不上思路,但是命題中指出存在兩種情況,讓我不禁想到枚舉(當然更多受swift本身影響),swift中的枚舉無比強大,倘若你是新手,建議再次閱讀官方文檔enumerate章節。Ok,接下來就是代碼部分開始設計枚舉類型。
代碼
聲明:一步步來,你會發現很有意思。
enum MyOptional{
case None
case Some
}
根據思路我們寫出了該枚舉類型,None
表示不存在值,Some
表示有值;不難發現定義的類型存在一些弊端,首先我們的變量可能是Int,String,Double,而此處未明確涵蓋;其次在有值情況下並未和實際值關聯。根據以上幾點對自定義枚舉進行修改,如下:
enum MyOptional<T>{
case None
case Some(T)
}
//特別申明 這種方式在swift1.2下是不支持的 由於和本節無關 就不扯了 但是我們自定義一個類來包裹
//貌似swift2.0是支持的....
enum Result<T>{
case Success(T)
case Failure(NSError)
}
我們巧妙使用了泛型匹配任何類型,並且利用枚舉的Associated Values對存在值x進行了關聯。爲了更好地使用我們會加上初始化方法聲明,代碼如下:
enum MyOptional<T>{
case None
case Some(T)
//生成一個有值的可選類型
init(_ value:T){
self = .Some(value)
}
//nil
init(_ nilLiteral:()){
self = .None
}
}
//my optional value
var myValue : MyOptional<Int> = MyOptional(2)
var myNil: MyOptional<Int> = MyOptional()
//測試下我們的蹩腳可選類型
switch myValue{
case .None:
println("nil")
case .Some(let x):
println("value is \(x)")
}
switch myNil{
case .None:
println("nil")
case .Some(let x):
println("value is \(x)")
}
看上去還不錯,但和swift中的可選類型有一定差距,以上僅僅只是讓你從另一面去了解可選類型。
命題二
可選類型中的??
解包運算符你能否自己實現? 自定義一個-->
解包運算符!
思路
解包行爲無非是那麼幾種,我們只要重載運算符即可。
代碼
infix operator -->{ associativity right precedence 110 }
func --><T>(optional:T?,defaultValue:T)->T{
// 我選擇了if-let解包
if let x = optional{
return x
}else{
return defaultValue
}
}
//測試下
var oo : Int? = nil
let r = oo --> 5 //輸出5
首先我們仍然使用泛型來聲明,那麼傳入一個可選類型optional,它可能有值=x
,可能不存在值(nil
),無值的情況下使用defaultValue
。
但是考慮到defaultValue
有時候並非是一個值,也許是一個閉包呢,反饋一個T
值。因此對函數稍加修改。
//代碼二
func --><T>(optional:T?,defaultValue:()->T)->T{
// 我選擇了if-let解包
if let x = optional{
return x
}else{
return defaultValue()
}
}
var rr = oo --> {7} //返回7
可以看到使用過程中我們對defaultValue
閉包必須明確表示,用{}
來包裹。可是單值情況下,用{}
包裹感覺很變扭,因此我們還需要稍加改動,利用autoclosure
特性來解決這一問題,最後代碼如下:
infix operator -->{ associativity right precedence 110 } //這個很重要
func --><T>(optional:T?,@autoclosure defaultValue:()->T)->T{
// 我選擇了if-let解包
if let x = optional{
return x
}else{
return defaultValue()
}
}
var rrr = oo --> 5+4 //可以看到 自動把 5+4 當做一個閉包來幹了
總結:可選類型難度不大,但是對初學者來說還是一道坎,畢竟以前沒有這種概念,多碼碼代碼自然就熟悉了。不知不覺寫到深夜了,洗洗睡了。