我遇到了一个有趣的用例。代码非常简单:
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方法不会返回T
;MXKTab
!=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/