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语言中的有一个很大的不同之处,就是它们不可以被" ...
随机推荐
- django细节
1.处理请求 1.1 /add/?a=4&b=5 这样GET方法进行[获取参数] from django.shortcuts import render from django.http i ...
- node.js分片上传文件
前端 : <html> <head> <title>分片上传文件</title> </head> <body> <div ...
- winform代码生成器(二)
代码下载 地址 http://pan.baidu.com/s/1nuZjyat 接着说 上文继续说,这次我们要生成主从表. 此方用到了第三方的 控件 DevExpress 的Gridview .大家可 ...
- [转]最全Redis面试题整理
此为转载文章,仅做记录使用,方便日后查看,原文链接:http://www.bieryun.com/3405.html 1.什么是Redis? 答:Redis全称为:Remote Dictionary ...
- hiveQL随笔
hiveQL中union all直接用于select 子句
- 静态化HttpClient
实现方法: public class HttpClientHelper { private static HttpClient _client; public static HttpClient Ge ...
- 【Linux】GDB程序调试
一.GDB简介 GDB是GNU发布的一款功能强大的程序调试工具.GDB主要完成下面三个方面的功能: 启动被调试程序. 让被调试的程序在指定的位置停住. 当程序被停住时,可以检查程序状态(如变量值) 二 ...
- ContentProvider启动浅析
一.自己的理解 对于content provide的启动我是这样认为的,要用ContentResolver去获得一个contentProvider,在这的获得的过程中, 1.如果本应用之前有conte ...
- windows下使用VNC进行远程连接
在 windows 电脑上安装 VNC,包含 VNC server 和 VNC viewer,如果仅需要被操控或操控他人,选择型下载安装 VNC server 或 VNC viewer 即可. 在需要 ...
- 关于java文件名字影响系统配置
测试OAM和OIF单点登录过程中,wlsh.sh中一个命令运行不过.查看一个java文件中有_en标示.修改名称,去掉_en后可以通过.