无法将swift泛型子类转换为泛型超类
我想在Swift中使用参数化类编写更好、更清晰的代码,但我遇到了一个奇怪的构建错误:无法将swift泛型子类转换为泛型超类,swift,xcode,generics,Swift,Xcode,Generics,我想在Swift中使用参数化类编写更好、更清晰的代码,但我遇到了一个奇怪的构建错误: 无法将“CustomAdapter”类型的值转换为预期的参数类型“TableTestParameterizedAdapter” 我真正想要的是能够使用一个方法(在适配器子类中重写)创建一个基本适配器类,该方法用于将单元格子类与相应的数据模型绑定,并避免每次强制转换 为了更好地理解我的意思,我将在下面发布代码 class TestParametrizedAdapter<C>: NSObject {
无法将“CustomAdapter”类型的值转换为预期的参数类型“TableTestParameterizedAdapter”
我真正想要的是能够使用一个方法(在适配器子类中重写)创建一个基本适配器类,该方法用于将单元格子类与相应的数据模型绑定,并避免每次强制转换
为了更好地理解我的意思,我将在下面发布代码
class TestParametrizedAdapter<C>: NSObject {
func doSmth(cell: C) {
}
}
class TableTestParametrizedAdapter<C>: TestParametrizedAdapter<C> where C:ETableViewCell {
}
class PeopleTableViewCell: ETableViewCell {
}
class CustomAdapter: TableTestParametrizedAdapter<PeopleTableViewCell> {
override func doSmth(cell: PeopleTableViewCell) {
}
}
class TestBaseController: UIViewController {
var adapter: TableTestParametrizedAdapter<ETableViewCell>?
override func viewDidLoad() {
super.viewDidLoad()
setAdapter(adapter: CustomAdapter()) // this is the line with build error
}
func setAdapter(adapter: TableTestParametrizedAdapter<ETableViewCell>) {
self.adapter = adapter
}
}
类testParameterizedAdapter:NSObject{
func doSmth(单元格:C){
}
}
类TableTestParameterizedAdapter:TestParameterizedAdapter,其中C:ETableViewCell{
}
类PeopleTableViewCell:ETableViewCell{
}
类CustomAdapter:TableTestParameterizedAdapter{
覆盖func doSmth(单元格:PeopleTableViewCell){
}
}
类TestBaseController:UIViewController{
var适配器:TableTestParameterizedAdapter?
重写func viewDidLoad(){
super.viewDidLoad()
setAdapter(adapter:CustomAdapter())//这是生成错误的行
}
func setAdapter(适配器:TableTestParameterizedAdapter){
self.adapter=适配器
}
}
我在其他一些帖子上读到过这方面的文章,有人指出GenericClass
和GenericClass)
Anywat,有什么解决办法吗?在这种情况下,我们如何使用Swift的参数化功能?我使用Swift 4
提前感谢。即使Swift支持自定义泛型中的差异,您的代码也将是错误的,因为您尝试使用只能处理PeopleTableViewCell实例的对象,而不是可以处理任何ETableViewCell的对象。如果这确实是您想要的,并且您不介意一些运行时检查,那么您可以通过少量的类型擦除来执行类似的操作:
class TestAnyAdapter: NSObject {
func doSmth(cell: Any) {}
}
class TableTestParametrizedAdapter<C>: TestAnyAdapter where C:ETableViewCell {
override func doSmth(cell: Any) {
guard let cell = cell as? C else {
return
}
self.doSmth(cell: cell)
}
func doSmth(cell: C) {}
}
类TestAnyAdapter:NSObject{
func-doSmth(单元格:任意){}
}
类TableTestParameterizedAdapter:TestAnyAdapter,其中C:ETableViewCell{
覆盖func doSmth(单元格:任意){
防护装置let单元=单元为?C else{
返回
}
self.doSmth(单元格:单元格)
}
func-doSmth(单元:C){}
}
其余的代码将与您已有的代码相同,只是没有编译时错误。我同意Konstantin的基本观点。这个代码根本不正确,斯威夫特告诉你这一点CustomAdapter.doSmth
不能接受任何任意的ETableViewCell
,但adapter
声明必须接受
根据您试图解决的实际问题,有许多解决方案。您表示希望编写“更好、更干净的代码”,这意味着您在现有代码中发现了过多的重复或强制转换。因此,您要做的是查看这些代码,并查看哪些代码被复制,然后我们可以帮助您设计通用解决方案以避免这种复制。这个问题没有普遍的答案;在一个方向上所做的抽象选择会使其他方向的灵活性降低。抽象是选择;它们需要在上下文中做出
在Swift中,您应该避免依赖子类化。有一些是必需的,因为要桥接到ObjC,但是关注Swift的代码应该避免子类。在您的特定示例中,有趣的类只有一个函数。如果这是真的,那么实现它就很容易了。使用一个功能:
func customAdapter(cell: PeopleTableViewCell) {}
class TestBaseController: UIViewController {
let adapter: (PeopleTableViewCell) -> Void = customAdapter
}
“但我真正的问题比这更复杂!”好吧。然后我们必须谈谈你真正的问题。正确地将这些东西抽象为最简单的形式,应该会得到最简单的解决方案。如果事情实际上有点复杂,可以使用结构和协议
protocol Adapter {
associatedtype Cell: UITableViewCell
func doSmth(cell: Cell)
}
struct CustomAdapter<Cell: ETableViewCell>: Adapter {
func doSmth(cell: Cell) {}
}
class TestBaseController: UIViewController {
let adapter: CustomAdapter<PeopleTableViewCell> = CustomAdapter()
}
协议适配器{
关联类型单元格:UITableViewCell
func doSmth(单元格:单元格)
}
结构自定义适配器:适配器{
func-doSmth(cell:cell){}
}
类TestBaseController:UIViewController{
let适配器:CustomAdapter=CustomAdapter()
}
我在掩饰你的问题,那就是如何使一个只接受PeopleTableViewCell
的函数在需要接受任何ETableViewCell
的函数时使用。那是不可能的。这不是Swift的限制;这是不可能的。正如康斯坦丁所解释的那样,你能做的最好的事情就是加上“什么也不做”或“崩溃”
如果您能更清楚地知道您试图修复的现有代码中的特定问题,我们可能会帮助您设计更好的解决方案。添加泛型本身并不能使您的代码“更好或更干净”(根据我的经验,大多数最好的解决方案根本不需要泛型)。让我们试着弄清楚一些事实
- 假设我们有泛型类
C
- 我们还有D类和D2类,其中D2是T的子类
那么C
不是C
的子类。它们只是不同的类型。(我们说不存在协方差。)
- 假设我们的泛型类
C
有一个子类C2
然后,C2
是C
的子类,C2
是C
的子类
因此,只要参数化类型相同,就存在多态性。但是如果参数化类型不同,即使参数化类型是类和子类,也没有协方差
(Swift可选和Swift集合在此处获得特殊的协方差豁免,但这已经融入到语言中;您不能使用相同的豁免。)