当前位置: 首页 > news >正文

闲聊Swift的枚举关联值

闲聊Swift的枚举关联值

枚举,字面上理解,就是把东西一件件列出来。 在许多计算机语言中,枚举都是一种重要的数据结构。使用枚举可以使代码更简洁,语义性更强,更加健壮。 Swift语言也不例外。但和其他语言相比,Swift的枚举有一个关联值的概念。什么是关联值呢?关联值是枚举项存放的额外的数据,这些额外的数据可以使枚举描述更复杂的结构 ,实现更复杂的需求。

下面定义了一个枚举,其中的每个枚举项都具有关联值。

enum Progress
{case begin(_ message:String)case progress (_ percent:Double,_ message:String   )case end(_ message:String )
}

在上述枚举定义中,begin项关联了一个类型为String的值,枚举项表示开始,其关联值进一步表示是什么具体过程。 progress项关联两个值,一个是百分比,一个是过程本身,枚举项表示进度,关联值则进一步表示是什么任务,到何种进度。有了关联值,我们就可以完整描述一个过程的具体进度了。

关联值看似平淡无奇,实则暗藏玄机。关联值既是Swift枚举不同于其他语言的独特之处,也是Swift枚举之所以强大的基础。

下面我们通过几个小例子简单说明。

问题一:将Double类型和String类型的值放到同一个数组中

这个问题好奇怪,为什么会有这样的问题?先不管为什么,先用枚举实现需求再说:


//定义枚举 
enum DoubleAndString{case isdouble(_ value:Double)case isstring(_ value:String)}//定义枚举数组let  myarr:[DoubleAndString] = [.isdouble(3.14),.isdouble(0.15926),.isstring("两个黄鹂鸣翠柳"),.isdouble(2.718),.isstring("一行白鹭上青天"),.isdouble(0.15926),]//使用数组myarr.forEach{switch $0{case .isdouble (let value):// value 是Double类型,可直接使用print("this is a double item \(value+1)")case .isstring (let value ):print("this is a string  item \(value)")}}

可以看到,我们通过定义了一个DoubleAndString枚举类型及其关联值,很轻易地将Double类型和String类型的值存放到一个数组中。

也许你会觉得这个很容易,用Any 数组不是也可以解决吗?如下使用Any数组的代码,貌似比枚举还简洁一些:

let  myarrA:[Any] = [3.14,0.15926,"两个黄鹂鸣翠柳",2.718,"一行白鹭上青天",0.15926,true,false]

但是,它的主要问题是:用Any数组没有语义。我们可以在这个数组中放Double类型,也可以放String类型,但因为是Any类型,没有什么能够阻止我们放布尔类型,如truefalse,或其他任何类型。另外一个问题是使用困难,因为没有类型,使用前必须进行类型判断和类型转换,如下代码:

 myarrA.forEach{if  $0  is Double{//$0 是Any类型,使用前需进行转换let d = $0 as! Double   print("double item: \(d+1)")}else{ if  $0  is String {print("string item: \($0)") }else{print("bad item: \($0)")       }}}

Any数组是一个巨大的盒子,进去容易出来难。因为它没有分门别类,找起来特别费劲,而且在使用前还得进行类型转换。枚举同样也是一个盒子,但已经按照各种case分门别类,语义清晰,使用容易,孰优孰劣,一目了然。

相信更多的人会问,把DoubleString放到一个数组中有什么实际意义吗?确实没有什么实际意义,但却可以揭示Swift枚举的本质:Swift枚举实际上是一个值的容器,我们可以通过它将不同类型的值(关联值)存放到同一个聚合类型(如数组中),并以高度语义化方式使用,这正是许多程序设计需要的非常有用的特性。

问题二:如何给枚举动态增加新的枚举值

Java语言的枚举功能其实也比较强大,可以通过构造函数传入复杂的对象,但有个头痛的问题,枚举项一旦设定,就不能够增加新的项了,因而上述需求在Java语言中无法用枚举实现,只能用普通的类实现,这样就完全不能够享受枚举的便利性了。在Swift中,这样需求可以用枚举直接实现。

比如,我们要对CSDN的文章标签建模,内置标签只有下面几项;如下Swift代码就可以实现:

enum CsdnTag
{case javacase swiftcase mysql
}

但要实现增加自定义标签功能,我们还需要增加一个 custome 枚举项,该枚举项自带一个String类型的关联值,表示自定义的标签,另外,我们还需要增加了一个getTag()函数,统一将内部标签和自定义标签转换为字符串:

enum CsdnTag
{case javacase swiftcase mysqlcase custome(_ tag:String)func getTag()->String{switch self{case .custome( let tag) :return tagdefault : return "\(self)"}}    }

下面是使用枚举的代码:

//定义标签var csdnTags:[CsdnTag] = [.java,.swift,.mysql,//自定义三个标签.custome("python"),.custome("redis"),.custome("vaadin")]  //使用标签csdnTags.forEach{print ($0.getTag())}

问题三:如何用枚举简化网络请求。

网络调用的简化的模型如下:

  • 调用成功,返回正确的数据
  • 调用失败,返回错误信息,包括错误代码,错误信息

根据上面这两种情况,我们直接定义如下枚举:

enum NetResult
{case success (_ data :String  )case error(_ errorCode:Int,_ errorString:String)
}

可以看到,建模过程是直截了当的,这是使用枚举的最大优势。

NetResult为基础,我们设计网络调用函数如下:

func fetchData(strUrl:String,resultHandler:(NetResult)->Void)
{//网络调用处理//网络调用完成,处理调用结果,假设调用成功var isSuccess = falseif isSuccess  {resultHandler(.success("这里是网络调用返回的数据"))}else{resultHandler(.error(202,"非法地址"))}   
}

使用上述调用:

   fetchData(strUrl:"www.blog.csdn"){ result inswitch result{case .success(let data) :  print ("data is:\(data)")case .error (let errorCode,let errorString):print("Network error:errorCode=\(errorCode),errorString=\(errorString)")}}

读者可以思考一下不使用枚举时该如何处理网络调用?无论如何设计,一定都比上述枚举方法繁琐许多。

小结

西方有一句谚语:拿起锤子,看什么都是钉子。枚举就是Swift语言中的锤子。小伙伴们,赶紧回家拿起你的锤子吧…

相关文章:

闲聊Swift的枚举关联值

闲聊Swift的枚举关联值 枚举,字面上理解,就是把东西一件件列出来。 在许多计算机语言中,枚举都是一种重要的数据结构。使用枚举可以使代码更简洁,语义性更强,更加健壮。 Swift语言也不例外。但和其他语言相比&#xf…...

抓取Instagram数据:Fizzler库带您进入C#爬虫程序的世界

引言 在当今数字化的世界中,数据是无价之宝。社交媒体平台如Instagram成为了用户分享照片、视频和故事的热门场所。作为开发人员,我们可以利用爬虫技术来抓取这些平台上的数据,进行分析、挖掘和应用。本文将介绍如何使用C#编写一个简单的Ins…...

Codeforces Round 933 (Div. 3) A~D

比赛链接 : codeforces.com/contest/1941 A . Rudolf and the Ticket 直接暴力即可 ; #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \n #define lowbit(x) (x&(-x)) #define sz(a) (int)a.size() #define p…...

《vtk9 book》 官方web版 第3章 - 计算机图形基础 (3 / 5)

3.8 演员几何 我们已经看到了光照属性如何控制演员的外观&#xff0c;以及相机如何结合变换矩阵将演员投影到图像平面上。剩下的是定义演员的几何形状&#xff0c;以及如何将其定位在世界坐标系中。 建模 计算机图形学研究中的一个重要主题是建模或表示物体的几何形状。…...

pytorch 函数整理

pytorch 函数整理 method_code.init.code.co_argcount&#xff1a;获取method_code.init 函数的输入变量的数目&#xff1b; input_params method_code.init.code.co_varnames&#xff1a;获取method_code.init 函数的输入变量的名称列表&#xff1b; __enter__和__exit__魔…...

docker实战之制作filebeat镜像

一&#xff0c;下载filebeat-6.5.4安装包&#xff1a; https://www.elastic.c o/downloads/beats 二&#xff0c;拉取centos:7镜像 docker pull centos:7 三&#xff0c;将下载的filebeat包放在~/filebeat下&#xff08;自定义就好&#xff09; 四&#xff0c;创建名为fileb…...

【DAY11 软考中级备考笔记】数据结构 查找和排序

数据结构 查找和排序 3月12日 – 天气&#xff1a;晴 1. 顺序查找 顺序查找就是简单的从头一个一个的进行比较&#xff0c;注意它的平均查找长度 2. 折半查找 折半查找和二叉排序树一致&#xff1a; 优点&#xff1a;查找效率很高 缺点&#xff1a;要求必须是循序存储并且表中…...

华为机考:HJ102 字符统计

华为机考&#xff1a;HJ102 字符统计 描述 方法1 先将所有字符计算数量&#xff0c;在对比其中字符的assic码 #include<iostream> #include<vector> #include<algorithm> #include<string> using namespace std; bool cmp(pair<char, int> a,…...

安装配置HBase

HBase集群需要整个集群所有节点安装的HBase版本保持一致&#xff0c;并且拥有相同的配置&#xff0c;具体配置步骤如下&#xff1a; 1. 解压缩HBase的压缩包 2. 配置HBase的环境变量 3. 修改HBase的配置文件&#xff0c;HBase的配置文件存放在HBase安装目录下的conf中 4. 首…...

【更新】数字金融与企业ESG表现:效应、机制与“漂绿”检验数据集(2011-2022年)

参照温亚东&#xff08;2024&#xff09;的做法&#xff0c;本团队对来自统计与决策《数字金融与企业ESG表现&#xff1a;效应、机制与"漂绿"检验》一文中的基准回归部分进行复刻 一、数据介绍 数据名称&#xff1a;数字金融与企业ESG表现 参考期刊&#xff1a;《统…...

手写简易操作系统(五)--获得物理内存容量

前情提要 上一章中我们进入了保护模式&#xff0c;并且跳转到了32位模式下执行。这一章较为简单&#xff0c;我们来获取物理内存的实际容量。 一、获得内存容量的方式 在Linux中有多种方法获取内存容量&#xff0c;如果一种方法失败&#xff0c;就会试用其他方法。其本质上是…...

机器学习之DeepSequence软件使用学习3-预测突变效应

import theano import numpy as np import sys import pandas as pd import scipy #scipy 模块是 Python 中用于科学计算和数据分析的重要模块之一。它包含了许多高级的数学函数和工具&#xff0c;包括数值积分、优化、线性代数、统计等。 from scipy.stats import spearmanr #…...

Linux文件与文件系统的压缩

文章目录 Linux文件与文件系统的压缩Linux系统常见的压缩命令gzip&#xff0c;zcat/zmore/zless/zgrepbzip2&#xff0c;bzcat/bzmore/bzless/bzgreppxz&#xff0c;xzcat/xzmore/xzless/xzgrepgzip&#xff0c;bzip2&#xff0c;xz压缩时间对比打包命令&#xff1a;tar打包命令…...

ubuntu 中进入python 编辑如何退出到命令行

文章目录 在Python解释器&#xff08;交互式命令行&#xff09;中&#xff0c;你可以使用 exit()函数或 CtrlD&#xff08;在Unix/Linux/macOS上&#xff09;或 CtrlZ然后输入 Enter&#xff08;在Windows上&#xff09;来退出Python解释器并返回到命令行。 以下是具体的步骤&a…...

2024.3.12 C++

1.思维导图 2.自己封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height),定义公有成员函数: 初始化函数:void init(int w, int h)更改宽度的函数:set_w(int w)更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show() #include <iostream…...

飞塔防火墙开局百篇——002.FortiGate上网配置——透明模式配置(Transparent)

透明模式配置 开启透明模式创建策略 在不改变现有网络拓扑前提下&#xff0c;将防火墙NGFW以透明模式部署到网络中&#xff0c;放在路由器和交换机之间&#xff0c;防火墙为透明模式&#xff0c;对内网网段192.168.1.0/24的上网进行4~7层的安全防护。 登陆FortiGate防火墙界面&…...

代码随想录算法训练营第52天|300.最长递增子序列 674.最长连续递增序列 718.最长重复子数组

300.最长递增子序列 这道题还挺简单的&#xff0c;咱们设置dp[i]表示到第i个数字时的递增子序列的最长的值&#xff0c;那么dp[i]就要遍历从0到i-1的数&#xff0c;也就是看看当前这个数字是否比前面的数字大&#xff0c;如果大的话就看看现在的子序列长度是否会长于前面那个数…...

分享一些开源的游戏仓库

1.CnC_Remastered_Collection 红色警戒95版本 https://github.com/electronicarts/CnC_Remastered_Collection gitee仓库分流&#xff1a;https://gitee.com/loswdarmy/CnC_Remastered_Collection 2.Far-Cry-1-Source-Full 孤岛惊魂1 https://github.com/StrongPC123/Far-Cry-…...

Java详解:单列 | 双列集合 | Collections类

○ 前言&#xff1a; 在开发实践中&#xff0c;我们需要一些能够动态增长长度的容器来保存我们的数据&#xff0c;java中为了解决数据存储单一的情况&#xff0c;java中就提供了不同结构的集合类&#xff0c;可以让我们根据不同的场景进行数据存储的选择&#xff0c;如Java中提…...

Centos7 使用docker来部署mondb

参考官方手册&#xff1a; https://www.mongodb.com/docs/manual/tutorial/install-mongodb-community-with-docker/#std-label-docker-mongodb-community-install 使用脚本快速安装docker curl -fsSL https://get.docker.com -o get-docker.sh | bash get-docker.sh使用 Doc…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...