Swift如何处理协议,是否有解决此错误的方法?
编译器不会编译以下代码,因为它断断续续地声明: 协议类型Swift如何处理协议,是否有解决此错误的方法?,swift,protocols,Swift,Protocols,编译器不会编译以下代码,因为它断断续续地声明: 协议类型Fooesque无法符合Fooesque,因为只有具体类型才能符合协议 protocol{var-bar:Int{get-set} 类FooStruct:Fooesque{var bar=42} 结构条{ typealias MyFoo=F var foo:MyFoo init(foo:MyFoo){self.foo=foo} } 结构风{ var someSpecificFoo:Fooesque func process(){let ba
Fooesque
无法符合Fooesque
,因为只有具体类型才能符合协议
protocol{var-bar:Int{get-set}
类FooStruct:Fooesque{var bar=42}
结构条{
typealias MyFoo=F
var foo:MyFoo
init(foo:MyFoo){self.foo=foo}
}
结构风{
var someSpecificFoo:Fooesque
func process(){let bar=bar(foo:someSpecificFoo)}//错误行
}
var whee=whee(someSpecificFoo:FooStruct())
显然这是一个bug,因为someSpecificFoo
已经声明为符合Fooesque
的具体实例(这就是var someSpecificFoo:Fooesque
的意思)
如果我们试图通过将其更改为,var someSpecificFoo:somefooesque
进行修复,那么错误编译器会说:
属性声明不透明的返回类型,但没有可从中推断基础类型的初始值设定项表达式
现在,它不仅无法像普通表达式那样自动合成初始值设定项表达式,而且即使我们手动添加一个初始值设定项表达式,它也将失败。添加:
init(foo:F){self.foo=foo}
。。。不会修复任何问题,只会将错误消息更改为:
无法将类型F
的值分配给类型some Fooesque
。。。即使F符合Fooesque!太坏了
有没有人找到解决这个问题的办法
到目前为止,我找到的唯一修复方法是简单地将
@objc
添加到第一行和import-Foundation
,在这种情况下,它可以完美地工作。我不是一个Swift编译器专家,但我不认为这是真的
显然这是一个bug,因为someSpecificFoo已经声明为符合fooseque的具体实例(这就是var someSpecificFoo:fooseque的意思)
问题似乎恰恰是这样。该声明没有任何具体内容。它可以是任何符合美食风格的东西。当您创建一个以F
作为协议Fooesque
的条形图时,您的意思是Fooesque
应该符合Fooesque
,这是它无法做到的。只有具体类型才能做到这一点
如果将行更改为var someSpecificFoo:FooStruct
,那么它似乎可以工作。但也许那不是你想要的
我不确定你到底想做什么,因为这些类型都是虚构的,但也许一个更具体的例子会有所帮助
干杯 它不是一个有缺陷的编译器;这相当于你对泛型约束的误解
Bar
是一种通用类型,可以用符合Fooesque
的特定类型具体化
例如,您可以有一个条
类型。此具体类型具有以下init声明:
init(foo: FooStruct)
Bar
不接受任何符合Fooesque
的类型-它只接受FooStruct
它显式地不是
,但您希望它的行为是这样的,在概念上执行以下操作:
let f: Fooesque = ...
let bar = Bar(foo: f)
你希望上面的钢筋混凝土类型是什么
编译器根据参数的类型推断F
为Fooesque
,因此它尝试创建一个具体的类型Bar
,但失败了,因为作为协议的Fooesque
,不符合其他协议,包括自身
但是你可能会说,不,我不希望泛型类型是
Fooesque
;我想要符合Fooesque
的类型
好的,哪一个?比方说,在上面的示例中,它是FooStruct
:
let f: Fooesque = ....
let bar = Bar<FooStruct>(foo: f) // ERROR
让f:Fooesque=。。。。
让bar=bar(foo:f)//错误
再次出现错误,因为Bar
需要一个FooStruct
作为参数,而不是任何Fooesque
类似地,如果您有一个AnotherFooStruct:fooseque
,那么您将有一个Bar
类型,期望将AnotherFooStruct
作为参数
因此,类似地,如果您有任何(通用)的F
类型,在您的示例中别名为MyFoo
,那么Bar
只接受MyFoo
类型,而不是Fooesque
MyFoo
类型是什么,是在编译时根据传入参数的静态类型显式或隐式确定的。“当您创建一个以F作为协议fooseque的条时,您是说fooseque应该符合fooseque,但它不能做到。”这段代码根本不是这么说的:init(foo:F){self.foo=foo}
这意味着泛型类型F符合Fooesque。这并不意味着它是Fooesque。另外,我没有在这里做self.foo=F
,我只是在做self.foo=foo
,其中foo
是符合Fooesque
的类型F
,这是类型变量的唯一要求ode>some Fooesque
。我同意你的说法,那是代码的意思。当你用someSpecificFoo调用初始值设定项时,你实际上是在“传入”Fooesque作为F。someSpecificFoo没有具体的类型(编译器知道)所以它无法知道F应该是什么类型。F不能是协议,它必须是具体的类型。它显然不是init(foo:fooseque)
这不是我所期望的。但是我应该能够调用init(foo:MyFoo)Bar
上的Fooesque
类型值,因为MyFoo
只是F:Fooesque
的一个类型别名。任何someSpecificFoo:Fooesque
在引擎盖下都是FooStruct
(在我的示例中,这是唯一的可能性),所以当我调用Bar(foo:someSpecificFoo>)时