Swift 中关于”??”操作符
Swift 中关于”??”操作符
Swift 的语法在保证安全和健壮的基础上,又带有很多非常灵活的特性,比如 ?? 操作符就是其中一个。大家可能已经了解它,也可能有些同学不了解它,这里给大家整理了关于这个操作符值得一看的讨论。
?? 操作符简述
在展开讨论之前,我们先来了解这个操作符的作用是什么。这个操作符和 Optional 相关,让我们来看一个例子:
var a:Int?
print(a ?? 2) //2
?? 操作符的左边是一个 Optional 值,右边是一个普通值,它的作用就是,如果左边的 Optional 值为 nil, 那么就使用右边的普通值作为返回值,如果左边的 Optional 不为 nil,则返回左边的 Optional 解包后的值。
比如我们这个例子中,变量 a 的值是 nil,所以 print 语句输出的就是后面的默认值 2。
刚才那个例子,如果不用 ?? 操作符,那么就是这样的逻辑:
print(a == nil ? 2 : a)
让我们来看看 ?? 操作符的定义:
func ??(optional: T?, @autoclosure defaultValue: () throws -> T) -> T
把它简化一下,就是:
func ??(optional: T?, defaultValue: () throws -> T) -> T
它会接受一个 T 类型的 Optional 值,和一个 T 类型的普通值作为默认值, 然后返回一个解包后的 T 类型的值。这个最终返回值是要根据第一个参数是否为空来确定。
?? 操作符的一些讨论
?? 操作符可以让我们更方便的处理 Optional。 但它也存在一些小问题,Swift 的官方邮件组中大家就有讨论。比如这段代码:
func test(x: ((String) -> String)? = nil) {
let qf = { (p:String) -> String in return "tt" }
let fn = x ?? qf
fn("tt")
}
test 函数它接受另外一个 Optional 类型的参数,然后在它内部用 ?? 操作符判断传进来的函数 x 是否为 nil,如果是,则用内部的另外一个函数 qf 来替代它。
初步来看,这样的代码应该没有什么问题,?? 的左边的变量类型是 ((String) -> String)?, 而右边的变量类型是 (String) -> String, 符合 ?? 操作符的定义。
但这段对 ?? 操作符的使用在实际编译的时候报错了。 我们必须把 qf 也声明成 Optional 类型,才可以使用:
let qf:((String) -> String)? = { (p:String) -> String in return "tt" }
let fn = (x ?? qf)!
fn("tt")
这样虽然编译通过了,但却不符合 ?? 操作符的定义了。这次两边都是 Optional 类型,而表达式的返回值也是 Optional。
这时关于 ?? 在 Swift 邮件组中最近的一个讨论,最后的一次回复说这是 Swift 的一个 bug, 将会在 Swift 3.0 版本中修复,这时这个回复的原文:
?? 操作符两边的类型可以不一样
在邮件组里,还有一个讨论,大家可以看一下这段代码:
var a:Int?
print(a ?? "test")
注意哦,左边的 a 是 Int? 类型的, 而右边是一个 String 字符串。 这段代码在目前的 Swift 2.2 编译上是可以编译通过的。
这个话题讨论的比较多,比较合理的一个解释是 Swift 编译器会根据当前表达式所在的场景进行相应的向上转型。
比如作为 print 函数的参数,编译器会将它们都看做 Any 类型,因为 print 函数接受的就是 Any 类型的参数。所以这个语句可以编译通过。
如果这个语句用在这个场景,就会导致编译失败了:
let x = a ?? "test"
这次的场景,是将它的返回值赋值给 x。 但这次编译器就无法确定他们的通用类型,而将他们看做两个不同的类型,这样就导致编译失败了。
同样的,这段代码就可以编译通过:
let x = a ?? NSDate()
按照刚才的逻辑,那么因为后面的类型是 NSDate 它们都可以是 NSObject 的子类,所以编译器将它们都作为 NSObject 的通用类型来处理了。
而上面的那个例子 let x = a ?? "test" 因为后面的字符串是 Swift 中的 String 类型,编译器就无法找到它们的通用父类,就导致失败了。
当然这是目前的讨论和分析结果,大家也可以一起来思考,来讲你的分析与大家交流。
Swift 中关于”??”操作符的更多相关文章
- Swift中的as操作符
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交 ...
- [翻译]理解Swift中的Optional
原文出处:Understanding Optionals in Swift 苹果新的Swift编程语言带来了一些新的技巧,能使软件开发比以往更方便.更安全.然而,一个很有力的特性Optional,在你 ...
- Swift 中范围和区间如何使用?
虽然现在swift语言已经发展到了2.0版了,但是相信很多学习iOS开发的童鞋仍对swift语言存在各种各样的疑问,今天小编将为大家详细介绍swift中的范围和区间,下面我们一起来看看吧. Range ...
- Swift中的Void类型与空元祖表达式
可能有不少Swift开发者会忽略这么一个细节:在Swift中,Void类型其实是一个别名类型,而其真正的类型为(),即一个空元祖(empty tuple)! 这种语言特性给Swift带来了一些比较方便 ...
- Swift Explore - 关于 Swift 中的 isEqual 的一点探索
在我们进行 App 开发的时候,经常会用到的一个操作就是判断两个对象是否相等.比如两个字符串是否相等.而所谓的 相等 有着两层含义.一个是值相等,还有一个是引用相等.如果熟悉 Objective-C ...
- Swift Tips - 在 Swift 中自定义下标访问
Untitled Document.md input[type="date"].form-control,.input-group-sm>input[type="d ...
- Swift中使用构建配置来支持条件编译-b
在Objective-C中,我们经常使用预处理指令来帮助我们根据不同的平台执行不同的代码,以让我们的代码支持不同的平台,如: 1 2 3 4 5 6 7 8 9 #if TARGET_OS_IPHON ...
- 深圳尚学堂:Swift中的“!”和“?”
Swift中的"!"和"?"Swift,苹果于2014年WWDC发布的新开发语言,用于搭建基于苹果平台的应用程序.Swift是一款易学易用的编程语言,而且它还是 ...
- Swift中的"可溢出"算术运算符
大家知道Swift中拥有和C,Objc类似的算术运算符,它们分别是: + - * / % 但是你可能不知道这些Swift中的运算符和C,Objc语言中的有一个很大的不同之处,就是它们不可以被" ...
随机推荐
- frp使用总结
笔者所知并成功实现内网穿透的方法: 花生壳 (需要花8块钱,使用花生壳给的二级域名,这里不做介绍) ngrok (免费,但是每次重启服务二级域名会变,付费的$5每月不会变) frp(开源免费,需要有自 ...
- C#学习笔记11
1.List.BinarySearch():BinarySearch()采用的是二分搜索算法,要求元素已经排好序,其特点是假如元素没有找到,会返回一个负整数,该值的按位取反(~)结果是“大于被查找元素 ...
- 在windows环境下运行compass文件出现的错误提示解决方案
在windows环境下运行compass文件出现的错误提示解决方案 例如:经常在项目中运行grunt命令编译scss文件的时候,会出现下面的错误提示 (Encoding::CompatibilityE ...
- ArcGisJS实现地图常用工具条、距离测量和面积测量(非官方实例)
常用地图工具包括:平移.拉框缩小.拉框放大.全图.距离测量.面积测量.清除标记,距离测量.面积测量没有使用官方自带的组件代码. 1.距离测量 2.面积测量 3.源代码 <!DOCTYPE htm ...
- Weka:call for the EM algorithm to achieve clustering.(EM算法)
EM算法: 在Eclipse中写出读取文件的代码然后调用EM算法计算输出结果: package EMAlg; import java.io.*; import weka.core.*; import ...
- android 5.0 下载编译
CM的CM-12.0版本(对应Android5.0.2): $ repo init -u https://github.com/CyanogenMod/android.git -b cm-12.0 注 ...
- javax.servlet.ServletException: java.lang.NoClassDefFoundError: javax/el/ELResolver错误解决办法
今天不用eclipse.myeclipse等开发工具,纯手写JSP页面(有点作死)时突然出现以前从来没遇到过的问题,报错如下: HTTP Status 500 - java.lang.NoClassD ...
- 用java实现一个简单的单用户登陆功能的思路
引用 所谓“单用户单账户登录”是指:在同一系统中,一个用户名不能在两个地方同时登录. 我们参照 QQ 实现效果:当某账号在 A 处登录后,在未退出的情况下,如果再到 B 处登录,那么,系统会挤下 A ...
- javascript面向对象的写法01
类和对象 其他面向对象的语言类的语法是内置的,自然而然的事.javascript中有对象,但没有类的语法,类的实现需要模拟出来. 只需要把对象想成一个容器,里面存放一些属性或方法,把类想象成一个对象的 ...
- Android应用开发基础之五:网络编程(二)
HttpClient 发送get请求 创建一个客户端对象 HttpClient client = new DefaultHttpClient(); 创建一个get请求对象 HttpGet hg = n ...