作者:OlivIEr Halligon,原文链接,原文日期:2015-04-24
译者:walkingway;校对:小锅;定稿:numbbbbb
在模式匹配系列文章的第一d和第二d中,我们已经看到关于 switch 搭配很多类型的用法,包括元组(tuples
),范围(Range
),字符串(String
),符号(Character
)和一些其他类型。但是假如我们使用自定义的类型和模式匹配,又能擦出怎样的火花呢?
如果你在 switch
实例中这样写 case 1900..<2000
,那么 Swift 如何比较 switch 入口的单值与下面的范围?
答案非常简单:Swift 使用了 ~=
*** 作符。当你在 case 中使用 Range<I>
时,switch 可以对 I
进行匹配,这是因为 Range<I>
与 I
二者之间定义了 ~=
*** 作符:
func ~=<I : ForwardindexType where I : Comparable>(pattern: Range<I>,value: I) -> Bool
事实上,如果你写 switch someI
并加上 case arangeOfI
语句时,Swift 会尝试调用 arangeOfI ~= someI
来做匹配 *** 作(该表达式会返回一个 Bool 来通知是否匹配成功)
这就意味着你可以为自己的类型定义相同的 *** 作符 ~=
,这样就能保证这些自定义类型可以在 switch/case
语句中使用,我们也可以用相同的方式使用 Range
!
我们构造一个自定义的结构体:
struct Affine { var a: Int var b: Int}func ~= (lhs: Affine,rhs: Int) -> Bool { return rhs % lhs.a == lhs.b}switch 5 {case Affine(a: 2,b: 0): print("Even number")case Affine(a: 3,b: 1): print("3x+1")case Affine(a: 3,b: 2): print("3x+2")default: print("Other")}
最终打印的结果是 3x+2
!
值得注意的一点是:在使用自定义类型时,Swift 不知道 switch 是否穷尽了所有可能。例如,即使我们添加了 case Affine(a: 2,b: 1)
和 case Affine(a: 2,b: -1)
这两个子句,来覆盖到每一个正整数和负整数的情况,Swift 还是会强迫我们使用 default:
语句。
此外需要注意,不要搞混了参数的顺序:~=
的第一个参数(通常称为 lhs
,译指左手边)是你将要在 case
子句中使用的对象,第二个参数(通常称为 rhs
,译指右手边)是你使用 switch 传入的对象。
~=
还有很多其他用途。
例如,我们可以在第二d中登场的 Book
结构体中添加如下代码:
func ~= (lhs: Range<Int>,rhs: Book) -> Bool { return lhs ~= rhs.year}
现在测试一下:
let aBook = Book(Title: "20,000 leagues under the sea",author: "Jules Vernes",year: 1870)switch aBook {case 1800..<1900: print("19th century book")case 1900..<2000: print("20th century book")default: print("Other century")}
当然我不鼓励这样使用,将 Book 直接与一段整数范围比较并不能很清晰地展现我们的意图:『其实是想与 book 的出版年份进行比较』。更好的方式是在 switch 中直接传入 aBook.year
。但我们举这个例子只是为了展示 ~=
*** 作符的强大(另一个原因是我暂时想不到更好的例子了 总结
以上是内存溢出为你收集整理的模式匹配第三d: 自定义的模式匹配和语法糖全部内容,希望文章能够帮你解决模式匹配第三d: 自定义的模式匹配和语法糖所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)