在Swift中使用泛型不能将Type转换为T.

时间:2014-12-15 21:39:41

标签: generics swift

我遇到了一个有趣的用例。代码非常简单:

protocol MXKTabBarDataSource {
    func createTabAtIndex(tabIndex: Int) -> MXKTab
}

class MXKTabBar<T: MXKTab>: UIView {
    private var tabs = [T]()

    var dataSource: MXKTabBarDataSource?

    private func createTabs() {
        if self.dataSource != nil {
            for tabIndex in 0..<2 {
                // getting a compiler error here saying: 'MXKTab is not convertible to T'
                self.tabs.append(self.dataSource!.createTabAtIndex(tabIndex))
            }
        }
}

class MXKTab: UIView {
    var title: String?
}

我想知道为什么会这样。标签栏约束T到MXKTab,createTabAtIndex的返回类型也是MXKTab。

任何人都知道问题是什么以及如何解决?非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

如果MXKTab是一个类,那么此处的声明说明MXKTabBar可以使用MXKTab的任何子类创建。您正在调用数据源上的一个方法(我假设)返回一个MXKTab对象。但是,如果您使用某些子类MXKTabBar实例化MXKTab(例如,MXKPolkaDotTab,那么您的createTabs方法不会返回T; MXKTab!= { {1}}。

您可能想要做的是让您的数据源 MSXPolkaDotTab约束。以下是来自游乐场的一些示例代码,可以实现您想要的内容而不会抱怨:

T

基本上,您必须在实现类中指定TabType。

(更糟糕的想法是将你的dataSource返回的任何内容转换为class MXKTab {} class MXKSpecialTab: MXKTab {} protocol MXKTabBarDataSource { typealias TabType func createTabAtIndex(tabIndex: Int) -> TabType } class SpecialTabDataSource: MXKTabBarDataSource { typealias TabType = MXKSpecialTab func createTabAtIndex(tabIndex: Int) -> TabType { return MXKSpecialTab() } } ,这可能在实践中起作用但不是我在理论上推荐的东西。)

我不完全清楚这是一个使用选项的合适位置,但我需要看到更多代码才能真正理解它。