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

在这里插入图片描述

概览

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

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

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

在本篇博文中,您将学到以下内容:

  • 概览
  • 1. 什么是模式匹配?
  • 2. 模式匹配符
  • 3. 模式匹配在 switch 语句中的应用
  • 4. 威力大增:模式匹配重载
  • 总结

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

Let’s Go!!!😉


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

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

  • 哔哩哔哩 bilibili

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 = 11if 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 语境中让开发“简约而简单”。

感谢观赏,再会!😎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/452268.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VmwareWorkstationPro17安装Centos

保存到之前创建的文件夹里&#xff0c;和主机放在一起就好 接下来直接安装就好了

java数组学习

目录 1.数组概念 2.数组的定义 3.数组的静态初始化 4.地址值 5.数组元素访问 6.索引 7.数组的遍历 8.数组的动态初始化 9.数组两种初始化方式的区别 10.数组常见问题 1.数组概念 数组是一种容器&#xff0c;可以同来存储同种数据类型的多个值。但是数组容器在存储数据…

用GOGS搭建GIT服务器

GOGS官网 Gogs: A painless self-hosted Git service 进入文件所在目录 cd /usr/local/develop 解压文件 tar -xvf gogs_0.13.0_linux_amd64.tar.gz 解压之后 进入gogs 目录 cd gogs 创建几个目录 userdata 存放用户数据 log文件存放进程日志 repositories 仓库根目…

2018年苏州大学837复试机试C/C++

2018年苏州大学复试机试 要求 要求用C/C编程&#xff1b;对程序中必要的地方进行注释。上机规则 请在电脑桌面上新建一个文件夹文件夹名为考试姓名&#xff08;中文&#xff09;&#xff1b;考试完毕后&#xff0c;将所编写的文件放在上述文件中。 第一题&#xff08;20分&…

Kubernetes集群搭建

一、概述 Kubernetes是一个Google开源的全新的分布式容器集群管理系统&#xff0c;由于从第一个字母到字母s中间有8个字母&#xff0c;所以简称K8s。 二、准备 ip角色内存192.168.187.130master4G192.168.187.131node2G192.168.187.132node2G 小提示&#xff1a; 设置静态i…

代码随想录刷题笔记 DAY 21 | 二叉搜索树的最小绝对值差值 No.530 | 二叉搜索树中的众数 No.501 | 二叉树的最近公共祖先 No.236

Day 21 01. 二叉搜索树的最小绝对值差值&#xff08;No. 530&#xff09; 题目链接 代码随想录题解 1.1 题目 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差的绝对值。 示例 …

Caffeine史上最快的内存缓存

引言 在现代的Web应用程序中&#xff0c;缓存是提升性能&#xff0c;减少数据库负载&#xff0c;加快响应速度的关键技术之一。Spring Boot作为一个简化Spring应用开发的框架&#xff0c;提供了与多种缓存技术集成的支持。Caffeine是一个高性能&#xff0c;灵活的缓存库&#…

Transformer 自然语言处理(三)

原文&#xff1a;Natural Language Processing with Transformers 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第八章&#xff1a;使 transformers 在生产中更高效 在之前的章节中&#xff0c;您已经看到了 transformers 如何被微调以在各种任务上产生出色的结果。…

C++STL之容器

STL的概述 STL(Standard Template Library,标准模板库) STL的6大组件&#xff1a;容器、算法、迭代器、适配器、仿函数、空间配置 容器&#xff1a;存放数据 算法&#xff1a;操作数据 迭代器&#xff1a;算法 通过迭代器 操作 容器 适配器&#xff1a;为算法 提供更多的接口 …

SQL报错注入

SQL注入报错注入 报错注入原理:报错注入是通过特殊函数错误使用并使其输出错误结果来获取信息的在遇到有报错回显的时候&#xff0c;但是没有数据回显的情况下可以利用报错注入的函数: 1.floor():向下取整 2.extractvalue(): 对XML文档进行查询的函数&#xff0c;当参数的格式…

202416读书笔记|《总有人会拥抱满身带刺的你》——今天我请客,想请你快乐

202416读书笔记|《总有人会拥抱满身带刺的你》——今天我请客&#xff0c;想请你快乐 这是一篇暖萌轻松的绘本推荐记录书评&#xff0c;《总有人会拥抱满身带刺的你》纳米著&#xff0c;《今天我请客&#xff0c;想请你快乐》燕七著&#xff0c;都还不错&#xff0c;截取摘录了…

C++-模板基础

1. 泛型编程 大家在学习过程中一定写过swap函数吧&#xff0c;那么swap函数的可以写成很多种形式&#xff0c;因为形参的类型可以是任意类型&#xff0c;那么我们如果想用多种swap函数的话&#xff0c;就意味着我们必须写多个swap函数吗&#xff1f;不是的&#xff0c;C为了解…