我遇到了一个有趣的用例。代码非常简单:
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。
任何人都知道问题是什么以及如何解决?非常感谢您的帮助。
答案 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()
}
}
,这可能在实践中起作用但不是我在理论上推荐的东西。)
我不完全清楚这是一个使用选项的合适位置,但我需要看到更多代码才能真正理解它。