swift – 使用关联类型和泛型错误
以下代码给我一个在线返回p.foo(self)的错误.错误说:’P’没有名为’foo’的成员.
protocol P { typealias T func foo(c: C<T>) -> T func foo2() -> T } class C<T> { var p: P init (p: P) { self.p = p } func bar() -> T { return p.foo(self); } } 协议P定义了与任何专门的C类型正确匹配的关联类型.我错过了什么吗?或不?
在回答问题之前,我会重新命名这些类型,以使问题更清晰一些:
protocol P { typealias ElementType func foo(c: C<ElementType>) -> ElementType func foo2() -> ElementType } class C<T> { var p: P init (p: P) { self.p = p } func bar() -> T { return p.foo(self) } } 在这种情况下,您会收到三个编译错误: error: <EXPR>:8:12: error: protocol 'P' can only be used as a generic constraint because it has Self or associated type requirements var p: P ^ <EXPR>:9:14: error: protocol 'P' can only be used as a generic constraint because it has Self or associated type requirements init (p: P) { ^ <EXPR>:13:16: error: 'P' does not have a member named 'foo' return p.foo(self) ^ ~~~ 有趣的是第一个/第二个(他们指出相同的问题):“协议’P’只能用作通用约束,因为它具有自我或相关类型要求”. init <S:P>(p: S) { self.p = p } 这将消除初始化程序的编译器错误.现在编译器知道参数必须是P的子类型,有效的子类型总是指定ElementType是什么,所以它是快乐的. 但这并不能帮助你: var p: P 您仍然不能在这里使用不完整的类型P.你可能想要使用S,但是在这个时候,初始化器中的S和S之间没有连接,你将使用它作为变量的类型,但是它们显然需要相同. class C<T,S:P> { var p: S init (p: S) { self.p = p } func bar() -> T { return p.foo(self) } } 几乎完成了,现在你有一个正确指定的类型用于你的变量.但是没有你的协议规范是不正确的: func foo(c: C<ElementType>) -> ElementType C现在需要两个参数,您需要在这里指定.我们想在这里使用`C,但是我们不能: 错误::3:17:错误 : type 'P' does not conform to protocol 'P' func foo(c: C<ElementType,P>) -> ElementType ^ <EXPR>:2:15: note: associated type 'ElementType' prevents protocol from conforming to itself typealias ElementType 由于P未指定相关类型的ElementType,它不正确符合P,并且不能在符合P类型的地方使用.但有一个很好的特殊类型:自我.这引用了实现协议的实际类型,所以我们可以写下列内容: protocol P { typealias ElementType func foo(c: C<ElementType,Self>) -> ElementType func foo2() -> ElementType } 现在我们指定由任何确认类型实现的foo函数实际上使用指定的ElementType和实现类型本身的C.花哨,不是吗? 但是我们尚未完成,最后一个错误仍然存??在: error: <EXPR>:13:18: error: cannot convert the expression's type 'T' to type 'S.ElementType' return p.foo(self) 此时编译器知道如下: > p.foo(self)返回S的ElementType 但是没有什么可以告诉的,ElementType和T实际上是一样的,所以它不能确定这是否有效和抱怨.所以我们实际想要的是,S的ElementType总是和T一样,我们可以指定: class C<T,S:P where S.ElementType == T> { 完整代码: protocol P { typealias ElementType func foo(c: C<ElementType,Self>) -> ElementType func foo2() -> ElementType } class C<T,S:P where S.ElementType == T> { var p: S init (p: S) { self.p = p } func bar() -> T { return p.foo(self); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |