Я пытался привести массив или 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)
}
Полагаю, мне придется создавать разные протоколы для всех поддерживаемых типов без связанных типов. Это один путь или есть другой?