如何定义符合协议的对象数组?

eru*_*del 6 cocoa-touch ios swift

鉴于:

protocol MyProtocol {
    typealias T
    var abc: T { get }
}
Run Code Online (Sandbox Code Playgroud)

还有一个实现MyProtocol的类:

class XYZ: MyProtocol {
    typealias T = SomeObject
    var abc: T { /* Implementation */ }
}
Run Code Online (Sandbox Code Playgroud)

如何定义符合的对象数组MyProtocol

var list = [MyProtocol]()
Run Code Online (Sandbox Code Playgroud)

给出(以及大量的SourceKit崩溃)以下错误:

Protocol 'MyProtocol' can only be used as a generic constraint because it has Self or associated type requirements
Run Code Online (Sandbox Code Playgroud)

即使实际上定义了typealias MyProtocol.

有没有办法让符合协议的对象列表具有通用约束?

Ant*_*nio 3

问题在于使用协议的泛型对应项,类型别名。听起来很奇怪,但是如果你定义了类型别名,你就不能将协议用作类型,这意味着你不能声明该协议类型的变量、函数参数等。并且你不能将其用作某个协议的泛型对象。大批。

正如错误所述,您可以使用它的唯一用途是作为通用约束(如class Test<T:ProtocolWithAlias>)。

为了证明这一点,只需从协议中删除类型别名(注意,这只是为了证明,这不是解决方案):

protocol MyProtocol {
    var abc: Int { get }
}
Run Code Online (Sandbox Code Playgroud)

并相应地修改示例代码的其余部分:

class XYZ: MyProtocol {
    var abc: Int { return  32 }
}

var list = [MyProtocol]()
Run Code Online (Sandbox Code Playgroud)

你会发现它有效。

您可能对如何解决这个问题更感兴趣。我想不出任何优雅的解决方案,只有以下 2 个:

  • 从协议中删除类型别名并替换TAnyObject(丑陋的解决方案!!)
  • 将协议变成一个类(但这并不是在所有情况下都有效的解决方案)

但正如你可能会争辩的那样,我不喜欢其中任何一个。我可以提供的唯一建议是重新考虑您的设计并弄清楚是否可以使用不同的方式(即不使用类型别名协议)来实现相同的结果。