Swift如何处理协议是否有针对此错误的解决方法?

问题描述

编译器不会编译以下代码,因为它断然声明:

协议类型Fooesque无法符合Fooesque,因为只有具体类型才能符合协议。

protocol Fooesque { var bar: Int { get set } }
class FooStruct: Fooesque { var bar = 42 }
struct Bar<F: Fooesque> {
    typealias MyFoo = F
    var foo: MyFoo
    init(foo: MyFoo) { self.foo = foo }
}
struct Whee {
    var someSpecificFoo: Fooesque
    func process() { let bar = Bar(foo: someSpecificFoo) } // error line
}
var whee = Whee(someSpecificFoo: FooStruct())

显然这是一个错误,因为someSpecificFoo已经被声明为符合Fooesque的具体实例(这就是var someSpecificFoo: Fooesque的意思)。 >

如果我们尝试通过将其更改为var someSpecificFoo: some Fooesque来进行修复,那么越野车编译器会说:

属性声明了不透明的返回类型,但是没有可用于从其推断基础类型的初始化器表达式

现在,它不仅无法像正常情况一样自动合成一个初始化程序表达式,而且即使我们手动添加一个初始化程序表达式也会失败。添加

    init<F: Fooesque>(foo: F) { self.foo = foo }

...不能解决任何问题,只是将越野车错误消息更改为:

无法将类型F的值分配为类型some Fooesque

...即使F符合Fooesque!太破碎了!

有人找到这种混乱的解决方法吗?

到目前为止,我发现的唯一解决方法是简单地将@objc添加到第一行和import Foundation在这种情况下,它可以很好地工作。

解决方法

我不是Swift编译专家,但我不认为这是真的。

显然这是一个错误,因为someSpecificFoo已被声明为符合Fooesque的具体实例(这就是var someSpecificFoo:Fooesque的意思)。

似乎问题出在那。该声明没有具体内容。可以是符合Fooesque的任何内容。当创建带有F作为协议Fooesque的Bar时,是说Fooesque应该符合Fooesque的规定,而不能这样做。只有具体类型可以做到这一点。

如果将行更改为var someSpecificFoo: FooStruct,则它似乎可以工作。但这也许不是您要的。

不知道您实际上要做什么,因为这些类型都是如此构成的,但是也许有一个更具体的示例会有所帮助?

干杯!

,

它不是错误的编译器;而是您对泛型约束的误解。

Bar是一种通用类型,可以具体化为符合Fooesque的特定类型。

例如,您可以使用Bar<FooStruct>类型。此具体类型具有以下init声明:

init(foo: FooStruct)

Bar<FooStruct>不仅仅接受任何符合Fooesque的类型-它接受FooStruct

它明显是 init(foo: Fooesque),但是您可以通过在概念上执行以下操作来期望它的行为:

let f: Fooesque = ...
let bar = Bar(foo: f) 

您期望上方的Bar的具体类型是什么?

编译器根据参数的类型推断FFooesque,因此它尝试创建具体的类型Bar<Fooesque>,但失败了,因为Fooesque-作为协议-不符合其他协议,包括自身。


但是您可能会说,不,我不希望泛型类型为Fooesque;我想要一些符合Fooesque的类型。

好,哪一个?假设在上面的示例中为FooStruct

let f: Fooesque = ....
let bar = Bar<FooStruct>(foo: f) // ERROR

再次出现错误,因为Bar<FooStruct>期望以FooStruct作为参数,而不是任何Fooesque

类似地,如果您有AnotherFooStruct: Fooesque,那么您将拥有Bar<AnotherFooStruct>类型,并期望以AnotherFooStruct作为参数。

因此-类似地-如果您有任何(通用)F类型-在您的示例中别名为MyFoo-那么Bar<MyFoo>仅接受MyFoo类型-不是Fooesque

MyFoo的类型是在编译时确定的,它基于传入参数的静态类型来显式或隐式确定。