我试图将数组或var组合成ProtocolA ,但遇到了一些错误。
这里发生什么事情?
我创建了两个带有/不含associatedtype的协议,并使两个struct符合ProtocolA和ProtocolB。
protocol ProtocolA {
associatedtype ProtocolAType
var prop1: ProtocolAType { get set }
func description()
func methodA(param1: ProtocolAType) -> ProtocolAType
}
protocol ProtocolB {
func description()
}
extension ProtocolA {
func description() {
print(self)
}
func methodA(param1: ProtocolAType) -> ProtocolAType {
param1
}
}
struct StructA: ProtocolA, ProtocolB {
var prop1: Int
}
struct StructB: ProtocolA, ProtocolB {
var prop1: String
}我创建CustomCollection是为了传递某种类型。
struct CustomCollection<T> {
typealias Items = [T]
private var items: Items
init(items: Items) {
self.items = items
}
}
extension CustomCollection: ExpressibleByArrayLiteral {
init(arrayLiteral elements: T...) {
self.items = elements
}
}
extension CustomCollection: Collection {
typealias Index = Items.Index
typealias Element = Items.Element
var startIndex: Index { items.startIndex }
var endIndex: Index { items.endIndex }
subscript(index: Index) -> Iterator.Element {
get { items[index] }
set { items[index] = newValue }
}
func index(after i: Index) -> Index {
items.index(after: i)
}
}CustomCollection适用于非关联类型协议。
var items: CustomCollection<ProtocolB> = [StructA(prop1: 1), StructB(prop1: "1")]
for item in items {
item.description()
}我试图给methodA打电话,但下面有错误。
var item1: some ProtocolA = StructA(prop1: 1)
var item2: some ProtocolA = StructB(prop1: "1")
item1.description()
//Cannot invoke 'methodA' with an argument list of type '(param1: Int)'
var result1 = item1.methodA(param1: 1)
//Cannot invoke 'methodA' with an argument list of type '(param1: String)'
var result2 = item2.methodA(param1: "1")我不知道如何让[ProtocolA]
//Cannot convert value of type '[Any]' to specified type 'some ProtocolA'
//Property declares an opaque return type, but cannot infer the underlying type from its initializer expression
var items1: some ProtocolA = [StructA(prop1: 1), StructB(prop1: "1")]
//Property declares an opaque return type, but cannot infer the underlying type from its initializer expression
//Return type of var 'items2' requires that '[StructA]' conform to 'ProtocolA'
var items2: some ProtocolA = [StructA(prop1: 1), StructA(prop1: 1)]我想叫methodA**.**
for item in items1 {
item.methodA(2)
}
for item in items2 {
item.methodA("2")
}我不知道如何指定associatedtype
//Protocol 'ProtocolA' can only be used as a generic constraint because it has Self or associated type requirements
var items4: CustomCollection<ProtocolA> = [StructA(prop1: 1), StructB(prop1: "1")]
//An 'opaque' type must specify only 'Any', 'AnyObject', protocols, and/or a base class
var items5: some CustomCollection<ProtocolA> = [StructA(prop1: 1), StructB(prop1: "1")]我不想在呼叫站点使用铸造,如下所示
var items: some Collection = [StructA(prop1: 1), StructB(prop1: "1")]
for item in items {
if let item = item as? StructA {
item.methodA(param1: 4)
}
if let item = item as? StructB {
item.methodA(param1: "3")
}
}我想用下面这样的东西
var items: some CustomCollection<ProtocolA> = [StructA(prop1: 1), StructA(prop1: 2)]
for item in items {
item.methodA(param1: 4)
},我想我必须为所有支持的类型制定不同的协议,没有关联的类型。这条路还是另一条路?
发布于 2020-02-23 08:58:50
不幸的是你就是不能。
实际上,解释非常简单,因为Swift数组需要包含相同“类型”的元素。当您的协议没有关联类型时,这很简单,数组包含ProtocolB实例.
但是,当涉及关联类型(或自)时,ProtocolA是不够的。因为ProtocolA并不意味着任何事情,它需要它的关联类型。更准确地说,您不能在同一个数组中使用ProtocolA{Int}和ProtocolA{String}。
因此,当您声明一个变量或一个ProtocolA数组时,编译器无法知道什么是关联类型.有关联。
在某种程度上,这与泛型是一样的:
var x : Array = [3,4]
x = ["thing"] // You can't第一行推断类型为Array<Int>,因此不能分配字符串数组.
但当你写到:
var items: CustomCollection<ProtocolA> = [StructA(prop1: 1)]它不能推断,因为它需要的“真实”类型,将是CustomCollection<ProtocolA{Int}>,但没有这样的东西在迅速.
更糟的是,当你写:
var items: CustomCollection<ProtocolA> = [StructA(prop1: 1), StructB(prop1: "1")]您有ProtocolA{Int}和ProtocolA{String}的元素。
Note:当我编写ProtocolA{Int}时,它只是澄清协议本身需要它的关联类型,而不是某种语法的一种方式。
编辑:关于你的最后一个问题,你不能这样做吗?
protocol ProtocolAA {
func description()
}
extension ProtocolAA {
func description() {
print(self)
}
func methodA<T>(param1: T) -> T {
param1
}
}
struct StructA: ProtocolAA, ProtocolB {
var prop1: Int
}
struct StructB: ProtocolAA, ProtocolB {
var prop1: String
}
var items: CustomCollection<ProtocolAA> = [StructA(prop1: 1), StructA(prop1: 2), StructB(prop1: "X")]
for item in items {
item.methodA(param1: 4)
}https://stackoverflow.com/questions/60359536
复制相似问题