我有很多TableViewCells,一个是基类
BaseTableViewCell<T: BaseTableViewItem>: UITableViewCell{
public var item: T!
}
另一个是类似的子类
ATableViewCell: BaseTableViewCell<ATableViewItem>
BTableViewCell: BaseTableViewCell<BTableViewItem>
ATableViewItem和BTableViewItem是BaseTableViewItem的子类
问题是
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: item.cellIdentifier)
(cell as! BaseTableViewCell).item.title = "title"
return cell!;
}
并在cell as! BaseTableViewCell
无法将类型“ Example.ATableViewCell”(0x1078453f0)的值强制转换为“ Example.BaseTableViewCell”
我该怎么办?
ps:
之所以这样做,是因为我想改进项目https://github.com/JavenZ/ZJTableViewManager,在这个项目中,当我使用自定义单元格时,总是像let item = self.item as! ZJTextItem
这样写代码,我觉得使用起来有些棘手。
所以我尝试使用泛型。看来我还没有找到好方法。您可以在ZJTableViewManager中查看演示。
非常抱歉我的英语不好,我无法清楚表达自己的意思
答案 0 :(得分:1)
您似乎正在尝试将子类转换为其父类,这是不可能的。您可以向下转换(将超类广播到其子类),因为该子类具有与其父类相同的属性,因此,该超类实例的所有信息都可以在该子类的实例中找到位置。但是,子类中可以包含比父类更多的信息,因此其所有信息可能无法在父类中找到位置。
我也看不出为什么这样做是必要的。在将对象的类型指定为一个类的任何地方,都可以在其位置使用其子类。如果需要使用子类中超类的重写方法,则可以始终使用super
关键字。我不明白为什么需要进行向上转换(从子类到超类,您在做什么)。如果您可以阐明原因,也许我可以提供更多帮助,但是如果不必要的话,您应该避免up头。
答案 1 :(得分:0)
您只能转换彼此严格的子类/超类的东西。
例如,如果我有
class MyCell: UITableViewCell { ... }
那我可以说
let cell: UITableViewCell = MyCell() // Swift knows that MyCell inherits from `UITableViewCell`
我可以说
var someCell: UITableViewCell
...
let myCell = someCell as? MyCell // Swift knows that this might work
但是你不能说类似这样的话
let s: String = someCell
这些类型无关。
在您的情况下,您已经引入了泛型,因此,即使基本类位于继承链中,添加泛型变体也意味着它们不兼容。我不能这样说:
let cell: ATableViewCell<Int> = ATableViewCell<String>()
它们是不同的。
这样做会违反Liskov Substitution Principle。
考虑一个简单的通用类:
class SomeClass<T> {
var item:T
init(item: T) {
self.item = item
}
}
let a = SomeClass<Int>(item: 10)
print(a.item+10) // Prints 20
let b = SomeClass<String>(item: "10")
print(b.item+10) // Compiler error - You can't add a string and an integer
您可以看到我需要知道与泛型一起使用的特定 type ,以便了解可以进行哪些操作。我无法将SomeClass<String>
的实例分配给声明为SomeClass<Int>
的变量;有效操作集不兼容。
您也许可以使用具有关联类型的协议,然后使用类型擦除,以便可以将该协议与子类一起使用,但是在某些时候,您需要了解特定行中要处理的单元格的具体类型因此您将需要将dequeueReusableCell
的结果强制转换为该具体类。泛型和协议可能只会使事情变得更复杂。