Swift 入门之自定义类型的模式匹配(Pattern Matching)

在这里插入图片描述

概览

小伙伴们都知道 Swift 是一门简洁、类型安全、极富表现力以及“性感迷人”的编程语言。

和大多数语言一样,在 Swift 中也有一些隐藏着的、不为人知的宝藏特性。利用它们我们可以极大增加撸码的愉悦和成就感。

其中,模式匹配(Pattern Matching)便是如此!征服它,我们的 Swift 开发技能又可以大步迈上一个新的台阶。

闲言少叙,让我们马上开始模式匹配的探索之旅吧!

Let’s Go!!!😉


本篇博文对应的视频课,欢迎小伙伴们恣意观赏:

Swift趣味开发征服模式匹配(Pattern Match)


1. 什么是模式匹配?

模式匹配是一种让我们可以更简洁更便利的比较、检查和解析数据的方式。

不光在 Swift 语言中,模式匹配的概念在很多其它编程语言中都能大放异彩。

比如,在下面 ruby 代码中我们通过模式匹配快速的检查了正则表达式是否匹配指定的字符串:

irb(main):001:0> r = /[a-z]at/
=> /[a-z]at/

irb(main):002:0> r =~ "xat"
=> 0
irb(main):003:0> r =~ "11zat"
=> 2
irb(main):004:0> r =~ "1at"
=> nil

在 Swift 中的模式匹配与此类似,不过它们特别适用于 switch 语句的语境中。

那么 switch 语句如何适配模式匹配呢?答案是:用模式匹配符

2. 模式匹配符

在 Swift 语言中,模式匹配符为 ~=。在内置一些类型上它会退化为 == 操作符的行为:

let string = "hello"
let power = 11

if string ~= "hello", power ~= 11 {
   
    print("matched!")
}
/* 输出结果为:
matched!
*/

注意,Swift 中匹配符(~=)与 ruby 中(=~)是正好反过来的。

我们可以为任意自定义类型做匹配模式的适配:

struct Foo {
   
    static func ~=(pattern: Double, value: Foo) -> Bool {
   
        value.size == pattern
    }
    
    var size = CGFloat.zero
}

let foo = Foo()
if 0.0 ~= foo {
   
    print("matched!")
}
/*
输出结果为:
matched!
*/

这里有两点需要注意:

  1. 匹配模式方法可以定义在类型外面;
  2. 若还要做“逆向”匹配,则我们需要两个匹配方法;

以下是演示代码:

struct Foo {
   
    var size = CGFloat.zero
}

func ~=(pattern: Double, value: Foo) -> Bool {
   
    value.size == pattern
}

// 逆向匹配方法
func ~=(value: Foo, pattern: CGFloat) -> Bool {
   
    value.size == pattern
}

let foo = Foo()
if 0.0 ~= foo {
   
    print("matched!")
}

// 逆向匹配
if foo ~= 0.0 {
   
    print("matched too!")
}
/*输出结果为:
matched!
matched too!
*/

我们还可以对 Swift 标准库中的类型做扩展以支持匹配模式,比如让正则表达式支持 ~= 操作符:

let regex = /[a-z]at/

func ~=(pattern: String, value: Regex<Substring>) -> Bool {
   
    let result = try? pattern.firstMatch(of: value)
    return result != nil
}

if "11xat" ~= regex {
   
    print("matched!")
}
/*输出结果为:
matched!
*/

直接利用 ~= 匹配可以为我们开发带来一定便利,不过更好的 idea 是将其嵌入到 switch 语句中以发挥最大威力。

3. 模式匹配在 switch 语句中的应用

在 Swift 中 switch 语句背后那个“默默无闻的男人”恰好就是模式匹配操作符。

struct Foo {
   
    var size = CGFloat.zero
}

func ~=(pattern: Double, value: Foo) -> Bool {
   
    value.size == pattern
}

对于上面已经抱上模式匹配大腿的 Foo 类型,我们可以直接将其融入到 switch 语句中去:

let foo = Foo()

switch(foo) {
   
case 0:
    print("ZERO")
case 5:
    print("FIVE")
default:
    print("others")
}
/*输出结果:
ZERO
*/

4. 威力大增:模式匹配重载

如果小伙伴们以为这就结束了,那显然大家的格局还要再打开一些。

利用重载机制,我们可以让自定义类型在 switch 语句中的模式匹配更加大放异彩。

比如,如果除了直接比较 Foo#size 属性以外,我们还想判断该属性的值是否在一个范围中,这该如何是好呢?

很简单,我们对模式匹配符进行重载:

func ~=(pattern: ClosedRange<CGFloat>, value: Foo) -> Bool {
   
    pattern.contains(value.size)
}

有了上面的定义,现在我们可以在同一个 switch 语句中用两种方式来匹配 Foo 对象的值了:

let foo = Foo(size: 11)

switch(foo) {
   
case 0:
    print("ZERO")
case 5:
    print("FIVE")
case 0...11:
    print("Bingooo!!!")
default:
    print("others")
}

/* 输出结果为:
Bingooo!!!
*/

看到这里,小伙伴们是否都已摩拳擦掌,想在 Swift 中去尝试应用模式匹配更多的“奇思妙想”呢?

勇敢去爱,不畏将来,不念过往。
放手去爱,让爱如风般自由,如光般璀璨。

所以,勇敢的去吧!The brave are invincible!棒棒哒!💯

总结

在本篇博文中,我们讨论了在 Swift 中如何优雅的适配模式匹配,并介绍了如何使用模式匹配操作符重载机制在 switch 语境中让开发“简约而简单”。

感谢观赏,再会!😎

相关推荐

  1. GraphQL入门定义标量类型

    2024-02-04 14:44:01       18 阅读
  2. 深入Rust模式匹配与枚举类型

    2024-02-04 14:44:01       35 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-04 14:44:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-04 14:44:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-04 14:44:01       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-04 14:44:01       20 阅读

热门阅读

  1. 2024/2/3 备战蓝桥杯 4-2 排序

    2024-02-04 14:44:01       36 阅读
  2. 按照特定的规则对 HTML 标签进行分类的方法

    2024-02-04 14:44:01       31 阅读
  3. C#(C Sharp)学习笔记_运算符【四】

    2024-02-04 14:44:01       31 阅读
  4. 二级C语言笔试2

    2024-02-04 14:44:01       24 阅读
  5. NLP深入学习(十三):AdaBoost 算法

    2024-02-04 14:44:01       32 阅读
  6. serialVersionUID详解

    2024-02-04 14:44:01       29 阅读
  7. mhformer代码笔记

    2024-02-04 14:44:01       28 阅读
  8. 01背包,但是bit -枚举 + 位运算

    2024-02-04 14:44:01       26 阅读
  9. MySql -- my.ini

    2024-02-04 14:44:01       31 阅读
  10. Uni-app+Uni-cloud开发体验

    2024-02-04 14:44:01       33 阅读
  11. 剪辑思维大学习(Day1) - 年终Vlog混剪

    2024-02-04 14:44:01       32 阅读
  12. 全志H713 Android 11 :给AOSP源码,新增一个Product

    2024-02-04 14:44:01       30 阅读