欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[Swift2.0系列]新的匹配解包方式(初稿)

程序员文章站 2022-06-12 19:38:38
...

Optional Pattern

更新历史:

  1. 2015.10.31新增case-let其他写法

当变量存在值有可能缺失的情况下使用可选类型,官方文档如下定义:

  • There is a value ,and it equals x,值存在且等于x.
  • There isn't a value at all,值不存在!

本文今天不涉及基础语法,更多有关可选类型的内容,请看Why coding like this--自己创建一个可选类型一文。

Swift1.2和Swift2.0 解包方式

Swift1.2

早前我们都喜欢使用if-let或者??进行可选类型进行解包,形如:

//这是一个整数可选类型
let someOptional:Int? = 42   //你可以改成nil试试 会发现没有输出了

//以前的解包方式
if let x = someOptional{
  print("someOptional value is \(x)")
}
var y = someOptional ?? 4

Swift2.0

而如今,Swift2.0又一次创新,新增如下两种方式。不如先一睹风采:

//1
//新增使用enumeration匹配 也就是枚举匹配方式
if case .Some(let x) = someOptional{
  print("someOptional value is \(x)") //如果为nil 情况 可不会输出东西 因为匹配的是Some!
}
//2
//新增使用可选模式匹配

if case let x? = someOptional{
  print("someOptional value is \(x)") //不需要对x进行解包之类的东东
}

可选类型是一个枚举,存在case None 以及 case Some(T)两种情况,其中T是包裹的值。

对于case .Some(let x) = someOptional这种匹配模式,右边的someOptional是一个可选类型,完整定义是:let someOptional:Int? = 42,换种方式写成case .Some(42)显然两者是匹配的,那么顺水推舟般x = 42喽。倘若someOptional = nil了呢?依旧转换成case .None,这时候左右两边是不匹配的! 有关更多匹配文章,请见swift.gg站点文章。

对于case let x? 其实和case .Some(let x)是一个道理。

两种解包优势在哪里?

有人问if-let解包 和 if case let x? 解包有什么区别?说实话,博主目前也不清楚。希望有人告知,-

这并不意味着if case let x?没有存在的价值,例如

let arrayOptionalInts:[Int?] = [nil,1,2,3,nil,5]    //数组的类型是Int? 可选类型喽

//遍历是用for-in  
//swift 1.2写法

for x in arrayOptionalInts{
  if let y = x{
    print("Found a \(y)")//把非 nil 值输出来
  }
}

//swift 2.0写法
//把解包行为提前到for 语句中了
for case let number? in arrayOptionalInts{
  print("Found a \(number)")
}

有对比才有发现,确实这时候新语法更胜一筹。

拓展

下面我写了一个小例子,以角色游戏为背景,游戏中有玩家、NPC和怪物。如下声明:

// 游戏角色 有玩家 NPC 怪兽
enum GameRole{
    case Player(name:String)// 玩家要有名字
    case NPC(name:String,faction:String)//名字 所属阵营
    case Monster(name:String,element:Int)//怪物名字 属性 水火金木土 对应1-5
}


var roles = [
    GameRole.Player(name: "玩家一"),
    GameRole.Player(name: "玩家二"),
    GameRole.Player(name: "玩家三"),
    GameRole.Player(name: "玩家四"),
    GameRole.NPC(name: "NPC1", faction: "光明"),
    GameRole.NPC(name: "NPC2", faction: "黑暗"),
    GameRole.NPC(name: "NPC3", faction: "精灵"),
    GameRole.NPC(name: "NPC4", faction: "黑暗"),
    GameRole.Monster(name: "怪物1", element: 1),
    GameRole.Monster(name: "怪物2", element: 2),
    GameRole.Monster(name: "怪物3", element: 4),
    GameRole.Monster(name: "怪物4", element: 5),
]

// 早前使用方法
// 遍历整个角色
for role in roles{
    // 因为是枚举 所以要switch来匹配
    switch role{
    case .NPC:
        print("有 NPC 出没")
    default:
        break
    }
}

可以看到想要遍历所有roles中的NPC 比如先用for-in循环,随后再用switch来进行匹配找到NPC。代码过于冗余,甚是不爽啊。好在Swift2.0中引入的case let解包方式,以下会让你耳目一新:

for case .NPC in roles{
    print("NPC找到")
}

倘若我还想要NPC中关联的名字以及阵营呢?

for case let .NPC(name,faction) in roles{
    print("NPC找到 name:\(name) 阵营:\(faction)")
}

苛刻一点 我只想要黑暗阵营的NPC!

for case let .NPC(name,faction) in roles where faction == "黑暗"{
    print("NPC找到 name:\(name) 阵营:\(faction)")
}

恩.可能你还看不惯case-let这种写法,或许你对其还是无感。但是我若是这么写呢?

(2015.10.31更新)

for case .NPC(let  name, let  faction) in roles where faction == "黑暗"{
    print("NPC找到 name:\(name) 阵营:\(faction)")
}

如此纯正的枚举匹配,为此你还有疑惑? 倘若需要自定义匹配模式,需要重载func ~=(pattern:value)这一方法。

倘若你觉得文章不错,请关注我,点击喜欢。另外推荐swift技术群:392436022。