从swift协议存储/传递函数类型

时间:2017-06-16 12:37:51

标签: swift swift-protocols

这段代码崩溃了swift(3,3.1,4)编译器:

protocol Test {
    func f()
}
let x = Test.f // crash

我希望,或许是天真的,编译器会将x推断为具有签名(Test) -> (Void) -> Void的函数类型,稍后,我可以这样称呼它:

let y = SomeClassConformingToTest()
x(y)()

我想我的问题是:显然编译器应该执行除崩溃之外的其他操作,但是Swift目前是否支持这种语法?

1 个答案:

答案 0 :(得分:3)

正如你所说,编译器永远不会崩溃;这确实是一个错误,has been filed here。其中,Swift团队成员Slava Pestov说:

  

我们计划让MyProtocol.someInstanceMethod工作。你已经可以了   为类做这个,例如,

class Foo {
    func f() { ... }
}
let f: Foo -> () -> () = Foo.f
     

协议应该具有相同的行为:

protocol Foo {
    func f()
}
let f: Foo -> () -> () = Foo.f
     

我打算稍后解决这个问题。

截至2017年5月8日,错误报告现已标记为" In Progress",所以希望这将成为Swift 4.0的发布版本。

然而,在实现/修复之前 - 一个简单的解决方法就是使用闭包表达式,以便作为方法的部分应用程序的thunk与实例一起调用它:

protocol Test {
    func f()
}

struct S : Test {
    func f() {
        print("hello")
    }
}

let x: (Test) -> () -> Void = { $0.f }

let s = S()
x(s)() // "hello"

当然,如果您不需要中间部分应用功能,您可以说:

let x: (Test) -> Void = { $0.f() }

let s = S()
x(s) // "hello"