Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift如何处理协议,是否有解决此错误的方法?_Swift_Protocols - Fatal编程技术网

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>)时