前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >对Swift中some和any关键字的理解

对Swift中some和any关键字的理解

作者头像
珲少
发布于 2022-11-14 11:41:27
发布于 2022-11-14 11:41:27
1.1K01
代码可运行
举报
文章被收录于专栏:一“技”之长一“技”之长
运行总次数:1
代码可运行

对Swift中some和any关键字的理解

在最新Swift版本中(Xcode14,Swift5.7),如果协议中有使用泛型,则如果要将此协议作为参数类型,必须使用any关键字进行修饰。其实在Swift5.1中也引入过一个some关键字,any和some都适用于协议,这两个关键字从语义上和写法上对泛型的使用进行了优化。

1. any

我们知道,协议中会规定一些属性和方法,用来约束其他结构的实现。举个简单的例子,我们可以使用协议定义了一个可飞行的实例需要实现的方法和属性,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protocol Fly {
    var name:String {get set}
    func fly()
}

class Bird:Fly {
    var name = "Bird"
    func fly() {
        print(name + "Fly")
    }
}

func test(f: Fly) {
    f.fly()
}

test(f: Bird())

这个程序当前运行的很好,语义也很明确,即test的函数的参数需要是实现了Fly协议的任意类型,其实在此中情况下,虽然在调用是我们传入的是Bird实例,但是由于协议类型的约束较弱,在函数执行时编译器会将其解释成了Fly类型,实际上产生了类型丢失。尤其是当协议中有使用泛型时,此时上面的写法在最新的Xcode版本中会提示错误,需要我们添加any关键字。any关键字的意义其实就是实现上述的语义,将参数类型定义为遵守某个协议的任意类型,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import Foundation

protocol Fly {
    associatedtype T
    var name:T {get set}
    func fly()
}


class Bird:Fly {
    typealias T = String
    var name = "Bird"
    func fly() {
        print(name + "Fly")
    }
}

func test(f: any Fly) {
    f.fly()
}

let f = test(f: Bird())

2.some

针对于上面代码的应用场景,我们只需要约束参数的类型是遵守Fly协议的即可,但是有时候这并不够,有时协议中的函数会需要多个参数,我们需要使用泛型约束其参数的类型一致,例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import Foundation

protocol Fly {
    associatedtype T
    var name:T {get set}
    func fly()
    func add(a:T, b:T)
}


class Bird:Fly {
    typealias T = String
    var name = "Bird"
    func fly() {
        print(name + "Fly")
    }
    func add(a: String, b: String) {
        
    }
}

func test(f: any Fly) {
    f.fly()
    // 这里会报错 因为any Fly类型在运行时无法确定成某个具体的类型
    f.add(a: f.name, b: f.name)
}

test(f: Bird())

可以看到,上面的代码中,test函数会报错,核心的原因在于any Fly类型的语音是任意实现了Fly协议的类型,无论是编译时还是运行时,编译器都无法推导出此f参数的类型。要解决上面的问题,可以采用泛型的方式来改写,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func test<T:Fly>(f: T) {
    f.fly()
    f.add(a: f.name, b: f.name)
}

此时代码则没有任何问题了,some关键字其实也是用于这一种场景,其表示的是一种透明类型,在运行时编译器知道其具体的类型是什么,只是对调用方来说是抽象的。下面的写法与上面使用泛型的写法作用完全一致:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func test(f: some Fly) {
    f.fly()
    f.add(a: f.name, b: f.name)
}

整体看来,相对与泛型那种写法,使用some的写法语义更加清晰,风格上也与any刚好一致。

最后,我们再来总结下,整体看来,any和some都是用来描述语义的关键字,any和协议一起使用,表示的是语义比较传统,及遵守了某个协议的类型,具体什么类型编译器也不知道。而some和协议一起使用表示的是具象的一个类型,此类型编译时不知道,调用时也开发者来说也是透明的,但是编译器自己是知道的,它就是具体的一个类型。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-11-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
go mod使用
最近由于换工作,开始交接工作。整理以前的工作内容,由于组内就我一个在做go和大数据。 所以开发没有规划,当时是怎么快怎么来。go也是使用最传统的go path的方式管理的。都是手动管理依赖的。现在交接给他人,需要多人开发,发现很多问题。比如版本问题,各种依赖的问题等等。
若与
2020/05/18
1.6K0
Go mod包依赖管理工具使用详解
对比上面几点: 目前做的最好的也就 maven了,gradle没有使用过,不知道。
OwenZhang
2021/12/08
1K0
Go mod包依赖管理工具使用详解
[Golang]包管理
本文是本人在探索 Go 最新的包管理 Go Modules 的一些总结,希望能够更深入了解 Go 最新的包管理方式,以及在实际环境中将它很好的使用起来。
别打名名
2020/07/28
1.7K0
golang mod 入门
go modules 是 golang 1.11 新加的特性。现在1.12 已经发布了,是时候用起来了。Modules官方定义为:
goodspeed
2020/12/22
8490
Go Module详细使用教程,包管理不在难
go modules是 golang 1.11引入的新特性。模块是相关Go包的集合。modules是源代码交换和版本控制的单元。go命令直接支持使用modules,包括记录和解析对其他模块的依赖性。modules替换旧的基于GOPATH的方法来指定在给定构建中使用哪些源文件。
公号:咻咻ing
2020/03/04
20.6K0
Go Modules 介绍与基本操作
Go 自 1.11 以来,包含对 Module 版本的支持。初始原型 vgo 于 2018 年 2 月宣布。2018 年 7 月,Module 版本进入 Go 代码仓库主分支。
frank.
2020/11/09
4.5K0
Go Modules 介绍与基本操作
Go Module Notes
Go 1.11 版本包含了两个最重要的 feature 就是 module 和 web assembly。Golang官方自go1.11版本初步引入,go1.12版本正式支持go Modules官方包依赖管理工具。
筱竼
2022/08/18
1.5K0
Go Module Notes
go modules:使用 mod 管理项目依赖包,通过vendor实现一键分发编译包
在go语言1.11版本之前,没有modules机制,所有软件包都在安装在$GOPATH/src目录下。不同项目如果引用了同一个软件包的不同版本,就会造成编译麻烦。修改$GOPATH变量是当时一种比较简单的解决方案。
LIYI
2020/03/25
6.6K0
GoPath模式和GoMoudle模式的相爱相杀
相信看我文章的文章的童鞋,golang版本已经是1.3版本以上。如果你的版本还停留在1.3以下,那这篇文章可以做为你的提升之法。
happlyfox
2021/03/17
6650
Go项目管理
包被导入时,会执行init函数,优先于main函数,不能有参数和返回值,建议少用,仅用于全局变量初始化,或者单元测试初始化一些东西
用户9022575
2021/10/01
1K0
Go Modules知识点总结
起初Go语言在1.5之前没有依赖管理工具,若想引入依赖库,需要执行go get命令将代码拉取放入GOPATH/src目录下,作为GOPATH下的全局依赖,这也就意味着没有版本控制及隔离项目的包依赖;
Golang梦工厂
2023/02/26
8610
Go Modules知识点总结
Go语言重新开始,Go Modules的前世今生与基本使用
2020年腾讯内部的一份开发者报告显示,Go语言已经成为腾讯内部第二大后端开发语言,在腾讯每天有大量的Go开发者在做业务和平台开发,大量的团队和项目使用也暴露出一些问题,随着Go Modules的出现,类似于内部自签发证书、安全审计等这些问题也逐渐得到解决。 笔者在腾讯当前负责腾讯云在Go编程语言使用上的一些问题,2021年初开始负责内部goproxy服务并推广Go Modules使用,这些技术支撑了腾讯云、微信、腾讯视频、腾讯游戏、腾讯音乐、腾讯会议等明星产品,并与公司内部软件源团队、工蜂团队、
腾讯云开发者
2021/11/25
6690
Go mod的简单实践
Go mod简介: Go mod是官方推荐的包管理方式,开始于go1.11,在go1.12版本基本稳定,go1.13之后开始默认开启。
灰子学技术
2020/05/20
10.5K0
Go语言学习(十)| module 使用
go module 是在go 1.11版本才开始有的,需要将环境变量 GO111MODULE 设置为 on 才能正常使用
Mervyn
2020/07/21
3910
浅谈GoPath和Go Modules包管理
从v1.5开始开始引入vendor模式,如果项目目录下有vendor目录,那么go工具链会优先使用vendor内的包进行编译、测试等
仙人技术
2021/08/31
1.2K0
浅谈GoPath和Go Modules包管理
Go编程之相关命令工具记录
该命令可以借助代码管理工具通过远程拉取或更新代码包及其依赖包,并自动完成编译和安装,整个过程类似安装App一样;
全栈工程师修炼指南
2022/09/29
6280
Go——依赖管理
在Go1.5 release的版本的发布vendor目录被添加到除了GOPATH和GOROOT之外的依赖目录查找的解决方法。 查找依赖包路径的解决 当前包下的vendor目录 先上级的目录查找,直到找到scr的vendor目录 在GOPATH下面查找依赖包 在GOROOT目录下查找
羊羽shine
2019/05/29
1.4K0
Go语言基本环境变量与依赖管理
最近开始系统学习一下Golang这么新语言,记录一下它的基本环境变量配置以及依赖管理方式。编写本文的时候使用的Golang版本为go1.13.5 windows/amd64,其他版本不一定保证适合本文的内容。因为习惯,可能有时候把Go语言称为Go,有时候称为Golang。
Throwable
2020/06/23
9.3K1
Golang 1.16 中 Module 有什么变化?
golang 1.16 默认开启 Modules,即使不存在 go.mod,Go 命令现在默认情况下也会在 module-aware(模块感知)模式下构建包。
frank.
2021/03/09
2K0
GO -mod和​GO111MODULE设置的那些事
意味着,忽略vendor文件夹,且对代码引用的(import)库列表自动更新到go.mod文件中,适用于带网络的研发环境调试编译
粲然忧生
2024/06/06
1.3K0
GO -mod和​GO111MODULE设置的那些事
相关推荐
go mod使用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档