模式匹配第一弹: switch, enums & where 子句
从简单的 switch 到复杂的表达式、Swift 中的模式匹配可以变得相当强大。今天开始我们来探索一下 switch 炫酷的使用技巧,稍后一系列文章会更进一步,为大家带来更高级的模式匹配技法。 本文作为模式匹配的第一篇介绍文章,旨在抛砖引玉。 Switch 基本用法Swift 中最简单、最为常见的模式匹配就是 enum Direction { case North,South,East,West } // 可以很容易地切换枚举值 extension Direction: CustomStringConvertible { var description: String { switch self { case North: return "↑" case South: return "↓" case East: return "→" case West: return "←" } } } 但是 switch 可以更进一步,允许使用包含变量的匹配模式,并在匹配时绑定这些变量。这适用于带关联值的枚举对象: enum Media { case Book(title: String,author: String,year: Int) case Movie(title: String,director: String,year: Int) case WebSite(url: NSURL,title: String) } extension Media { var mediaTitle: String { switch self { case .Book(title: let aTitle,author: _,year: _): return aTitle case .Movie(title: let aTitle,director: _,year: _): return aTitle case .WebSite(url: _,title: let aTitle): return aTitle } } } let book = Media.Book(title: "20,000 leagues under the sea",author: "Jules Verne",year: 1870) book.mediaTitle 这种形式下的通用语法是 当 media 实例匹配其中一个条件,比如匹配第一个 case: 请注意,你可以将 let 写在整个表达式的前面,而不用再写在每个变量前,下面这两行代码是等价的: case .Book(title: let aTitle,author: let anAuthor,year: let aYear): … case let .Book(title: aTitle,author: anAuthor,year: aYear): … 上面的代码使用了通配符 使用固定的值记住 extension Media { var isFromJulesVerne: Bool { switch self { case .Book(title: _,year: _): return true case .Movie(title: _,director: "Jules Verne",year: _): return true default: return false } } } book.isFromJulesVerne 这个例子或许并没有什么实际意义,但是至少向你展示了如何绑定常量。我提到它是因为我们已经学习过将一个值绑定到一个变量上,然后判断该变量是否等于一个常量,而不是直接和这个常量进行模式匹配。 一个更有帮助和通用的例子看起来应该是这样的: extension Media { func checkAuthor(author: String) -> Bool { switch self { case .Book(title: _,author: author,director: author,year: _): return true default: return false } } } book.checkAuthor("Jules Verne") 注意这里尽管我们在 一次绑定多种模式在 Swift 2.2 中,我们不能一次绑定多种模式,所以下面的例子是不能正常工作的,因为我们尝试声明了一些变量用做 extension Media { var mediaTitle2: String { switch self { // 错误: 'case' 标签中含多种模式,变量是不能被声明的 case let .Book(title: aTitle,year: _),let .Movie(title: aTitle,year: _): return aTitle case let .WebSite(url: _,title: aTitle): return aTitle } } } 这在大多数情形下是可以理解的;你期望下面这些代码做些什么: case let .Book(title: aTitle,let .Movie(title: _,year: aYear)? 随后你该如何在代码中使用绑定的变量( 但是可能需要考虑的一个特例是当你尝试绑定相同名字和类型的变量时,这仍然是有意义的工作,就像上面例子中我们尝试在 cases 是 使用没有参数标签的元组注意当处理
作为附加的奖励,可以不用指定特定的元组来匹配任何关联值,所以下面三个表达式是相等的: case .WebSite // not specifying the tuple at all case .WebSite(_) // matching a single tuple of associated values that we don't care about case .WebSite(_,_) // matching individual associated values that we don't care about either 使用 Where 语句比起比较两个枚举,模式匹配允许更强大的方式,你可以在比较中添加条件,使用 where 从句,如下: extension Media { var publishedAfter1930: Bool { switch self { case let .Book(_,year) where year > 1930: return true case let .Movie(_,year) where year > 1930: return true case .WebSite: return true // same as "case .WebSite(_)" but we ignore the associated tuple value default: return false } } } 这样只有当左边的模式( 下一部分的计划这篇文章很简单,带你回顾了
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |