Optional chaining的秘密(二)

作为一名程序员,我们是不会甘心止步于语法的“甜”,我们有永恒的动力去揭开这层语法的外衣一看究竟:)。我们在《Optional chaining的秘密(一)》中指出了,在类型的后面使用?表示Optional类型,而?.则是map 方法的语法糖。

我们今天要研究的是在类型的后面使用!意味着什么?

ImplicitlyUnwrappedOptional

只要我们随便翻翻官方文档,我们就能知道,下面这段代码是编译不过的

let x: String? = "Hello,world"
func printString(str: String) {
    print(str)
}
printString(x) // error!!!!!!

原因就在于 xString? 声明为一个Optional<String>类型了,而方法printString()要求的参数是 String 类型,所以如果直接传递 x 会导致调用失败,如果我们希望方法调用成功,那么我们需要这样处理。

printString(x!)

我们需要使用 ! 强制对 x 进行拆封,使其还原为 String 类型。那么如果 ! 放在类型的后面意味着什么呢?

let x: String! = "Hello,world"
func printString(str: String) {
    print(str)
}
printString(x) // ok!!!!!!

文档把这种 let x: String! 称为隐式拆封(implicitly unwrapped),在 implicitly unwrapped 的帮助下,我们可以看到printString(x)中的参数x不需要强制拆封了。难道let x: String!为我们定义了一个String类型?no,no,no,no

我们在看一个长一点的例子。

public class Demo {
    public var subDemo: SubDemo! = nil
}

public class SubDemo {
    public let count: Int = 1
}

let demo: Demo! = Demo()
demo.subDemo = SubDemo()

let count = demo.subDemo.count

在这个代码片段中,我们有两处值得注意:

  • public var subDemo: SubDemo! = nil可以被声明为nil
  • let count = demo.subDemo.count 可以chaining式调用

第一点是比较容易解释的,subDemo之所以可以被声明为nil是因为,SubDemo!声明了一个ImplicitlyUnwrappedOptional类型,也就是说它不是一个普通的类型,如果它是一个普通的SubDemo类型,那么它一定不允许为nil.

如何完成链式的调用

那怎么解释第二点,链式调用呢?让我们循序渐进,我们现在有这样个方法,可以给一个string做扩展

extension String {
    static func appendingString(str: String) -> (String) -> String {
        return { str + $0 }
    }
}

var aStr = "Hello"
var bString = String.appendingString(aStr)("!")
var method = String.appendingString(aStr)
var cStr = method("!")

现在我们定义个操作符方法:+- 它可以帮助我们实现上面同样的功能

infix operator +- { associativity left }
func +-<T,Z>(obj:T, f:T->Z) -> Z {
    return f(obj)
}

通过这个中缀操作符的定义,我们可以这样实现给一个字符做扩展的功能。

let helloString = "hello" +- {
    String.appendingString($0)("!")
}

操作符 +- 接收两个参数,一个是字符串"hello",另外一个是闭包。而且通过associativity的声明,这种操作可以还可以产生一个连缀式调用。

let helloString = "hello" +- {
    String.appendingString($0)("!")
    } +- { String.appendingString($0)("!") }

说了这么多,不知道我们又没有注意,我们现在已经可以对 String 类型做类似 ?. 操作了,只是当前类型是String,我们现在要将其适用于ImplicitlyUnwrappedOptional类型。

infix operator +- { associativity left  }
func +-<T,Z>(obj:ImplicitlyUnwrappedOptional<T>, f:T->Z) -> ImplicitlyUnwrappedOptional<Z> {
    switch obj {
    case .Some(let x):
        return f(x)
    case .None:
        fatalError()
    }
}

我们重新实现操作符 +- 的定义,使其接收一个ImplicitlyUnwrappedOptional类型的参数并返回一个ImplicitlyUnwrappedOptional类型的值。方法体内容会对参数obj进行拆包,如果为nil则会报错,否则经过转换后返回ImplicitlyUnwrappedOptional,这不就是完整的implicitly unwrapped的工作过程吗?好,现在我们把String声明为implicitly unwrapped

var oldString: String! = "hello"  // String!

let helloString = oldString +- {
    String.appendingString($0)("!")
    } +- { String.appendingString($0)("!") }

这就是Optinal chainingimplicitly unwrapped 是的工作过程。

总结

以上代码在xcode 7.3上都测试通过。虽然代码没有swift的链式操作符代码那样漂亮,但这些功能确实可以通过纯swift代码来实现。希望这些内容有助于大家对optional更深入的理解。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 基础部分(The Basics) 当推断浮点数的类型时,Swift 总是会选择Double而不是Float。 结合...
    gamper阅读 1,261评论 0 7
  • 对各种值为"空"的情况处理不当,几乎是所有Bug的来源。 在我们的例子里,尽管tmp的值是nil,但调用tmp的r...
    AKyS佐毅阅读 10,496评论 1 13
  • Swift 是一门开发 iOS, macOS, watchOS 和 tvOS 应用的新语言。然而,如果你有 C 或...
    XLsn0w阅读 920评论 2 1
  • 聊聊费兰克的写作训练营 近来喜欢上了写作,而且想提高一下写作水平,又偶然知道了一个叫做费兰克的家伙花了十多万去学习...
    简单国平阅读 426评论 2 49
  • 江梅从一片混沌中醒来的时候,厚重的遮光窗帘严实地挡住了窗外的景象,因此她也无法辨认此刻到底是白昼还是黑夜。 黑暗中...
    _云本_阅读 240评论 0 1