我将如何使用具有符合协议的类型参数的泛型数组?

How would I use an array of generics with a type parameter conforming to a protocol?

有没有办法让泛型数组(或任何泛型类型)的类型参数符合协议?

protocol MyProtocol {}

struct MyStruct<T: MyProtocol> {
  let myProp: T
}

// Generic parameter 'T' could not be inferred
// Explicitly specify the generic arguments to fix this issue
let array1 = [MyStruct]()

// Value of protocol type 'MyProtocol' cannot conform to 'MyProtocol';
// only struct/enum/class types can conform to protocols
let array2 = [MyStruct<MyProtocol>]()

// Type 'Any' does not conform to protocol 'MyProtocol'
let array3 = [MyStruct<Any>]()

protocol MyProtocol2 {
  associatedtype T = MyProtocol
  var myProp: T { get }
}
extension MyStruct: MyProtocol2 {}
// Protocol 'MyProtocol2' can only be used as a generic constraint because it has Self or 
// associated type requirements
let array4 = [MyProtocol2]()

数组可以有 MyStruct 个具有不同类型参数的数组。

理想情况下,这应该有效:

struct MyStruct2<T: MyProtocol> {
  let myProp: T
  let myFunc: (T) -> Void
}

let array = [MyStruct2</* something? */>]()
array.forEach { [=11=].myFunc([=11=].myProp) }

我已阅读 ,但该解决方案在我的情况下不起作用,因为数组中的项目 MyStruct 具有 任何类型 符合至 MyProtocol.

我也看过Usage of protocols as array types and function parameters in swift和其他类似的问题,但解决方案也不合适。

要查看您的场景有什么问题,请忘记尝试声明此数组的类型,并尝试从实际对象中实际 制作 这样的数组:

protocol MyProtocol {}
struct MyStruct<T: MyProtocol> {
  let myProp: T
}
struct S1 : MyProtocol {}
struct S2 : MyProtocol {}
let myStruct1 = MyStruct(myProp: S1())
let myStruct2 = MyStruct(myProp: S2())
let array = [myStruct1, myStruct2] // error

编译器反击:"heterogeneous collection literal could only be inferred to '[Any]'"。这就是总结。 myStruct1myStruct2 的类型没有任何共同点,因此您不能将它们组成一个数组。

这就是为什么您无法将数组声明为同时包含它们的类型。没有这种类型。 myStruct1myStruct2的类型,即MyStruct<S1>MyStruct<S2>,是不相关的

我知道它们 看起来 相关,因为原始声明中的 "MyProtocol" 一词似乎提供了某种共性。但是"MyProtocol"这个词并没有指定类型;它在实际类型上指定了一个 constraint,表示无论这个类型是什么,它都必须是 MyProtocol 的 adopter。 S1 和 S2 是两种不同的类型,因此 MyStruct<S1>MyStruct<S2> 是两种不同的类型。您不能将它们放在一个数组中。 S1 和 S2 恰好都采用了 MyProtocol 的事实是无关紧要的。

部分困难可能在于您认为两个泛型类型在某种程度上是相关的,因为它们的参数化类型是相关的。事实并非如此。 classic 示例是 class 及其子 class:

class Cat {}
class Kitten: Cat {}
struct Animal<T: Cat> {}
let cat = Animal<Cat>()
let kitten = Animal<Kitten>()
let array2 = [cat, kitten] // error

我们得到了同样的编译错误。同样,您可能会想象可以将 catkitten 放在一个数组中,因为 Kitten 是 Cat 的子 class。但事实并非如此。 Animal<Cat>Animal<Kitten> 不相关的类型