如何将类型化数组转换为其中一种类型协议?

时间:2015-07-07 01:58:10

标签: ios swift

我在操场上有这个:

func foo(printables: [Printable]) {
    // do something
}

enum MenuOptions: String, Printable {
    case ChangePickup = "Change Pickup Time"
    case RequestSupport = "Request Support"

    var description: String {
        get {
            return self.rawValue
        }
    }
}
var menuOptions: [MenuOptions] = [.ChangePickup]
foo(menuOptions)
let printables = menuOptions as [Printable]    

最后两行都会产生编译错误。我希望将menuOptions隐式地转换为[Printable],但编译器会抱怨[MenuOptions] is not convertible to [Printable]错误。我错过了什么吗?

如果我menuOptions as! AnyObject as! [Printable]编译器没有抱怨并且代码正常工作,但这看起来很脏。有趣的是,做foo(menuOptions.map { $0 })也有效!这只是一个编译器错误吗?

2 个答案:

答案 0 :(得分:1)

您正在尝试创建一个约束于符合Printable协议的对象的泛型函数。只是以不同的方式定义它:

func foo<T: Printable>(printables: [T]) {
    // do something
}

该功能现在可以在您的上下文中使用。它将采用符合Printable的任何对象类型的数组。

以下是Generics上的相关文档,特别是Type Constraints

至于为什么这样做,但你的定义没有 - 这只是Swift语法。 Printable是一种协议,但T是一种类型(通用,但仍然是一种类型)。您希望您的函数接受符合协议(T)的任何类型(<T: Protocol>)。这就是语言的设计方式。

使用menuOptions as! AnyObject as! [Printable]可能在此示例中有效,但这是一种不好的做法。使用as!就像告诉编译器“相信我,这会起作用”。这在有限的情况下很好,但从长远来看会让你陷入困境。使用as!关闭编译器的类型检查,这意味着如果出现问题,它将在运行时发生,并且您的应用程序将崩溃。

同样,我强烈建议阅读上面链接的关于类型约束的文档。它详细解释了它。

答案 1 :(得分:0)

我发现这很有效。似乎Swift编译器并不那么聪明。

onBindViewHolder()

我不知道为什么这些不起作用

var menuOptions: [MenuOptions] = [MenuOptions.ChangePickup]
let printables:[Printable] =  menuOptions as! [Printable]
foo(printables)