TL;DR
Swift 中的实例方法是柯里化的。本质是把 self 当做隐式参数的类方法,它会返回一个给实例用的函数。
我们先定义一个简单的 struct,然后调用:
1 | struct aCls { |
其实,系统是这么帮你处理的1
2aCls.aFunc(ins)()
aCls.aPrint(ins)(str: "Hello")
最近在看 Swift 方法调用这方面的内容,这篇也是方法调用系列的一个番外篇。
柯里化
如果你还不了解 Currying,可以看这里
swift-evolution: Removing currying func
declaration syntax
虽然 Swift 3 已经把这玩意去掉了,不过这个概念还是对降低程序复杂度有一些帮助的。
发生了什么?
我们在这里使用 SIL 来进行辅助分析,如果你还不了解 SIL,先自己查查,我后面会有一篇专门说这个。
还是拿着上面的类声明来看。
1 | struct aCls { |
可以得到一大串代码,我们简单清理一下,得到如下:
1 | // aCls.aFunc() |
可以看到 SIL 中只有 aCls.aFunc(), aCls.aPrint(str:) 的声明实现,并没有表现出实例相关的方法。1
2
3
4
5// aCls.aFunc()
bb0(%0 : $aCls):
// aCls.aPrint(str:)
bb0(%0 : $String, %1 : $aCls):
而且在两处 bb0
这行,你可以看到参数列表的最后一位是一个 aCls 类型的对象,也就是实例对象。
进一步,我们调用实例变量就可以看到这个实例参数会被怎么使用了,比如在 aPrint(str:)
方法中我们调用了一个实例属性。
1 | // aCls.aPrint(str:) |
可以看到通过传入的实例,来进行和实例有关的操作,比如读取 property:bb0 %1: aCls
拿到实例变量%14 = struct_extract %1 : $aCls, #aCls.aPropStr // user: %15
取出属性的值,并在下面进行 copy 等操作。
总结
柯里化是一种很好的拆分思想,可以在有重复操作的情况下降低耦合,提高代码复用性。