Swift 3:从非命名类型继承

Swift 3: Inheritance from non-named type

我有以下 SSCIE:

protocol Foo {
    associatedtype Bar
    associatedtype Baz: (Self.Bar) -> Void

    var currentValue: Bar { get }
}

我想这样使用:

func call<T: Foo>(foo: T, callback: @escaping T.Baz) {
    DispatchQueue.main.async {
        callback(foo.currentValue)
    }
}

但是编译失败,报错:

Inheritance from non-named type '(`Self`.Bar)'

当我使用 (Bar) -> Void(Foo.Bar) -> Void 时,这也无法编译。


Sadly, Googling this didn't come up with any useful results.

有谁知道这个错误的含义、我做错了什么以及如何纠正它?

Swift 3 中的关联类型只能受 "is-a" 约束。所以你的 Bar 必须是 Any。顺便说一下,这并不是什么大的限制;)。换句话说,你可以删除它。

但是,(Self.Bar) -> Void 是函数类型,您不能像这样约束关联类型。

如果要定义回调类型,可以使用类型别名:

protocol Foo
{
    associatedtype Bar
    typealias Callback = (Self.Bar) -> Void

    var currentValue: Bar { get }

    func f(callback: Callback) -> Void
}

使用 @escaping 目前在类型别名中不起作用(请参阅 SR-2316 及其各种副本)。这是一个应该很快得到修复的错误(截至 2016 年 8 月)。所以你现在必须拼写出来:

func call<T: Foo>(foo: T, callback: @escaping (T.Bar) -> Void) {
    DispatchQueue.main.async {
        callback(foo.currentValue)
    }
}

更新: 按照 Hamish 的建议,我提交了 SR-4967。一旦有任何消息,我将更新此 post。

如前所述,函数类型不能用作关联类型。

试试这个:

func call<T: Foo>(foo: T, callback: @escaping (T.Bar) -> Void) {
    ...
}

并且使用此设计,您可以为您提出的每个特定辅助函数(在您的示例中为 call)混合匹配函数类型(对于 callback arg)。