首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在vars或数组中使用associatedType协议?在SWIFT5.1中如何使用?

如何在vars或数组中使用associatedType协议?在SWIFT5.1中如何使用?
EN

Stack Overflow用户
提问于 2020-02-23 05:42:57
回答 1查看 232关注 0票数 1

我试图将数组或var组合成ProtocolA ,但遇到了一些错误。

这里发生什么事情?

我创建了两个带有/不含associatedtype的协议,并使两个struct符合ProtocolAProtocolB

代码语言:javascript
复制
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是为了传递某种类型。

代码语言:javascript
复制
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适用于非关联类型协议。

代码语言:javascript
复制
var items: CustomCollection<ProtocolB> = [StructA(prop1: 1), StructB(prop1: "1")]
for item in items {
    item.description()
}

我试图给methodA打电话,但下面有错误。

代码语言:javascript
复制
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]

代码语言:javascript
复制
//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**.**

代码语言:javascript
复制
for item in items1 {
    item.methodA(2)
}
for item in items2 {
    item.methodA("2")
}

我不知道如何指定associatedtype

代码语言:javascript
复制
//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")]

我不想在呼叫站点使用铸造,如下所示

代码语言:javascript
复制
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")
    }
}

我想用下面这样的东西

代码语言:javascript
复制
var items: some CustomCollection<ProtocolA> = [StructA(prop1: 1), StructA(prop1: 2)]
for item in items {
    item.methodA(param1: 4)
}

,我想我必须为所有支持的类型制定不同的协议,没有关联的类型。这条路还是另一条路?

EN

回答 1

Stack Overflow用户

发布于 2020-02-23 08:58:50

不幸的是你就是不能。

实际上,解释非常简单,因为Swift数组需要包含相同“类型”的元素。当您的协议没有关联类型时,这很简单,数组包含ProtocolB实例.

但是,当涉及关联类型(或自)时,ProtocolA是不够的。因为ProtocolA并不意味着任何事情,它需要它的关联类型。更准确地说,您不能在同一个数组中使用ProtocolA{Int}ProtocolA{String}

因此,当您声明一个变量或一个ProtocolA数组时,编译器无法知道什么是关联类型.有关联。

在某种程度上,这与泛型是一样的:

代码语言:javascript
复制
var x : Array = [3,4]
x = ["thing"] // You can't

第一行推断类型为Array<Int>,因此不能分配字符串数组.

但当你写到:

代码语言:javascript
复制
var items: CustomCollection<ProtocolA> = [StructA(prop1: 1)]

它不能推断,因为它需要的“真实”类型,将是CustomCollection<ProtocolA{Int}>,但没有这样的东西在迅速.

更糟的是,当你写:

代码语言:javascript
复制
var items: CustomCollection<ProtocolA> = [StructA(prop1: 1), StructB(prop1: "1")]

您有ProtocolA{Int}ProtocolA{String}的元素。

Note:当我编写ProtocolA{Int}时,它只是澄清协议本身需要它的关联类型,而不是某种语法的一种方式。

编辑:关于你的最后一个问题,你不能这样做吗?

代码语言:javascript
复制
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)
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60359536

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档