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

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?
}

我不知道为什么。Tab bar约束T到MXKTab,createTabAtIndex的返回类型也是MXKTab。
有人知道问题是什么以及如何解决?非常感谢你的帮助。

最佳答案

如果MXKTab是一个类,那么您在这里的声明说明可以用MXKTabBar的任何子类创建MXKTab。您正在数据源上调用一个方法,该方法(我假设)返回一个MXKTab对象。但是,如果用MXKTabBar的某个子类实例化MXKTab(比如说,MXKPolkaDotTab,那么createTabs方法不会返回TMXKTab!=MSXPolkaDotTab
您可能需要做的是让您的数据源也受到T的约束。下面是一些来自一个操场的示例代码,它实现了您想要的目标,而且没有很多抱怨:

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()
    }
}

实际上,您必须在实现类中指定TabType。
(更糟糕的想法是将数据源返回的任何内容都转换为T,这在实践中可能有效,但在理论上不是我推荐的做法。)
我并不完全清楚这里是否适合使用optionals,但我需要看到更多的代码才能真正理解这一点。

关于generics - 在Swift中使用泛型无法将类型转换为T,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27493635/

10-10 18:25