当前位置: 首页 > 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…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...