Why Coding Like this -------Optional揭祕 自己寫一個可選類型類

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 當做一個閉包來幹了

總結:可選類型難度不大,但是對初學者來說還是一道坎,畢竟以前沒有這種概念,多碼碼代碼自然就熟悉了。不知不覺寫到深夜了,洗洗睡了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章