我将如何使用具有符合协议的类型参数的泛型数组?
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]'"。这就是总结。 myStruct1
和 myStruct2
的类型没有任何共同点,因此您不能将它们组成一个数组。
这就是为什么您无法将数组声明为同时包含它们的类型。没有这种类型。 myStruct1
和myStruct2
的类型,即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
我们得到了同样的编译错误。同样,您可能会想象可以将 cat
和 kitten
放在一个数组中,因为 Kitten 是 Cat 的子 class。但事实并非如此。 Animal<Cat>
和 Animal<Kitten>
是 不相关的类型 。
有没有办法让泛型数组(或任何泛型类型)的类型参数符合协议?
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]'"。这就是总结。 myStruct1
和 myStruct2
的类型没有任何共同点,因此您不能将它们组成一个数组。
这就是为什么您无法将数组声明为同时包含它们的类型。没有这种类型。 myStruct1
和myStruct2
的类型,即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
我们得到了同样的编译错误。同样,您可能会想象可以将 cat
和 kitten
放在一个数组中,因为 Kitten 是 Cat 的子 class。但事实并非如此。 Animal<Cat>
和 Animal<Kitten>
是 不相关的类型 。