使用具有通用关联类型的枚举的Swift协议

时间:2015-05-27 12:47:24

标签: swift generics enums protocols

我试图在swift中创建一个使用通用枚举的协议。 编译器抛出此错误:Protocol can only be used as a generic constraint because it has associated type requirements

剪短代码:

enum GenericEnum<T> {
    case Unassociated
    case Associated(T)
}

protocol AssociatedProtocol {
   typealias AssociatedType
   func foo() -> GenericEnum<AssociatedType>
}

let bar = [AssociatedProtocol]()

您可以找到更长的示例here

有人知道这个问题的解决方案吗?

1 个答案:

答案 0 :(得分:4)

问题在于:想象一些后续的代码行。

// none of this will compile...
var bar = [AssociatedProtocol]()
bar.append(GenericEnum.Associated(1))
bar.append(GenericEnum.Associated("hello")
let foo = bar[0].foo()

foo是什么类型的?是GenericEnum<Int>还是GenericEnum<String>?或者都不是?

这尤其是一个问题,因为枚举,如结构,是“值类型”。这意味着它们的大小取决于它们的含量。请使用以下代码:

let x = GenericEnum.Associated(1)
sizeofValue(x)  // 9 - 1 byte for the enum, 8 for the Int
let y = GenericEnum.Associated("hello")
sizeofValue(y)  // 25 - 1 byte for the enum, 24 for the String

具有相关类型的协议只能用于约束泛型函数。所以这没关系:

func f<T: AssociatedProtocol>(values: [T]) {
    var bar = [T]()  // T is an instance of a specific 
                     // AssociatedProtocol where T.AssociatedType
                     // is fixed to some specific type
}

但单独使用它是没有意义的(至少使用Swift的当前版本1.2 - 新功能可能会启用版本中的其他内容。)

如果您需要在运行时以动态多态方式使用协议,则需要抛弃类型。然后它可以用作固定大小的参考。