当元素类型为协议[Swift]时,无法在通用Array类上调用扩展方法 [英] Can't call extension method on generic Array class when element type is a Protocol [Swift]

查看:47
本文介绍了当元素类型为协议[Swift]时,无法在通用Array类上调用扩展方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据注释中引用的错误消息,以下操作失败.它已经煮到最低限度,因此下面的代码没有明显的实用价值.我只是试图处理真正奇怪的错误消息(以我的观点).我想将数组声明为 [P] 而不是 [S] 的原因是因为数组内容通常具有运行时多态性.

The following fails as per the error message quoted in the comment. It has been boiled down to the bare minimum, so the code below has no apparent practical value. I'm just trying to get a handle on the truly bizarre (in my opinion) error message. The reason I want to declare the array as [P] and not [S] is for the usual run-time polymorphism of the array contents.

protocol P {
    func sp()
}

struct S: P {
    func sp() {}
}

extension Array where Element: P {
    func am() {}
}

func t() {
    let goodA = [S]()
    goodA.am() // No problem

    let badA = [P]()
    badA.am() // Error: '[P]' is not convertible to 'P'
}

推荐答案

协议声明定义了新的独立类型.尽管它们的行为与类,枚举和结构不同,但它们可以充当变量或属性的类型(前提是没有相关的类型约束,但要坚持).例如

Protocol declarations define new independent types. While they do behave differently than classes, enums, and structs, they can act as the type for a variable or property (provided there are no associated type constraints, but hold on). For instance

protocol MyProtocol {}
let myConst: MyProtocol // myConst has type `MyProtocol`

在带有泛型where子句的协议扩展中,有两种方法可以约束所讨论的泛型类型:使用:_ == .两者之间是有区别的.

In a protocol extension with a generic where clause, there are two different ways to constrain the generic type in question: either with :_ or ==. There is a difference between the two.

使用:_

冒号指定泛型类型与指定的类型或协议匹配.它可以被解读为继承自"或符合".例如,扩展名中指定的所有内容仅在关联类型符合 Equatable 或从 SomeClass

The colon specifies that the generic type is something matching the type or protocol specified. It can be read as 'inherits from' or 'conforms to'. For example, anything specified in the extensions apply only when the associated type conforms to Equatable or inherits from SomeClass

protocol AnotherProtocol {
    associatedtype MyType
}

class SomeClass {}

extension AnotherProtocol where MyType: SomeClass {}
extension AnotherProtocol where MyType: Equatable {}

使用==

泛型where子句中的 == 运算符指定泛型类型完全等于指定的类型,而没有其他类型.下面的代码给出了编译时错误

The == operator in a generic where clause specifies that the generic type is exactly the type specified and no other. The code below gives a compile-time error

class CustomType {}
class CustomTypeII: CustomType {}
class MyClass: AnotherProtocol { typealias MyType = CustomTypeII }

extension AnotherProtocol where MyType == CustomType {
    func myFunc() {}
}

let instance = MyClass()
instance.myFunc() // Error: `CustomTypeII` is not the same type as `CustomType`

== 运算符不能用于将通用类型限制为具有关联类型的协议.编译器会抱怨该协议具有关联的类型要求.

The == operator cannot be used to constrain a generic type to a protocol with associated types. The compiler will complain that the protocol has an associated type requirement.

protocol ThirdProtocol {}

extension ThirdProtocol where Self == AnotherProtocol {} // Error: `AnotherProtocol` has associated type requirements

从本质上讲,规范是模棱两可的:没有单一的 AnotherProtocol 类型,就像没有单一的 Array 类型一样.协议中的关联类型的作用类似于通用类型的通用参数.在这里,需要使用冒号来指定通用类型是某种" AnotherProtocol 类型(不透明类型是由于需要指定具有关联类型约束的协议的特定类型",但这是不可能的.

In essence, the specification is ambiguous: there is no single AnotherProtocol type, much in the same way that there is no single Array type. The associated type in a protocol acts similarly to the generic arguments of a generic type. Here, the use of a colon is needed to specify that the generic type 'is some' AnotherProtocol type (opaque types follow from the need to specify a specific 'type' of a protocol with associated type constraints, but that is beyond the question).

您的扩展程序

Array 的扩展名仅适用于其元素为某种符合协议类型 P 的某种类型的数组实例,不适用于其元素为该类型的数组 P .不符合自己的协议类似于不继承自自己的类.

The extension of Array applies only to array instances whose elements are some type that conforms to the protocol type P, which does not apply to arrays whose elements are the type P. Protocols not conforming to themselves is akin to classes not inheriting from themselves.

这是一个旧线程,但希望能有所帮助.

This is an old thread, but hopefully this helped.

这篇关于当元素类型为协议[Swift]时,无法在通用Array类上调用扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆