2017-08-31 119 views
2

我想在子类雨燕的通用类,但无论我做什么,编译器只是不断抱怨,或者更糟,段错误。子类泛型类

这是我编译它时最接近的,但后来我无法创建子类的实例,因为编译器出于某种原因无法推断出什么是T

protocol GenericDataSourceCellProtocol { 
    associatedtype ModelType 
    var model: ModelType? {get set} 
} 

struct MyCellState {} 

class MyCell: UITableViewCell, GenericDataSourceCellProtocol { 
    var model: MyCellState? 
} 

class Generic2DDataSource<U, T> 
where U:GenericDataSourceCellProtocol, U:UITableViewCell, T == U.ModelType { 

    let items: [[T]] 
    init (items: [[T]]) { 
     self.items = items 
    } 
} 


class SubclassedDataSource: Generic2DDataSource<MyCell, MyCellState> {} 

let state = MyCellState() 
let items = [[state]] 
let datasource = SubclassedDataSource(items: items) 
// cannot convert value of type '[Array<MyCellState>]' to expected argument type '[[T]]' 

有没有办法让这项工作?我错过了什么?

回答

1

有很多东西会在这里,极不平凡的雨燕系统的东西。但是,这是你要去的吗?

protocol GenericDataSourceCellProtocol { 
    associatedtype ModelType 

    var model: ModelType? {get set} 
} 

struct MyCellState {} 

class MyCell: UITableViewCell, GenericDataSourceCellProtocol { 

    typealias ModelType = MyCellState 

    var model: MyCellState? 
} 

class Generic2DDataSource<U> where U: GenericDataSourceCellProtocol, U: UITableViewCell { 

    typealias T = U.ModelType 

    let items: [[T]] 

    init(items: [[T]]) { 
     self.items = items 
    } 
} 


class SubclassedDataSource: Generic2DDataSource<MyCell> { 

} 

let state = MyCellState() 
let items = [[state]] 
let datasource = SubclassedDataSource(items: items) 

而且,我觉得你有什么应该在技术上是有效的,因为我发现,如果我是你的代码改成这样就会使错误消失:

protocol GenericDataSourceCellProtocol { 
    associatedtype ModelType 

    var model: ModelType? {get set} 
} 

struct MyCellState {} 

class MyCell: UITableViewCell, GenericDataSourceCellProtocol { 

    typealias ModelType = MyCellState 

    var model: ModelType? 
} 

class Generic2DDataSource<U, T> where U: GenericDataSourceCellProtocol, U: UITableViewCell, T == U.ModelType { 

    let items: [Array<U.ModelType>] 

    init(items: [Array<U.ModelType>]) { 
     self.items = items 
    } 

    func thing() -> T { 
     let value = items[0][0] 

     return value 
    } 
} 

class SubclassedDataSource: Generic2DDataSource<MyCell, MyCellState> { 
} 

通知我添加了一个功能thing到基类。我这样做,是因为在Xcode中,您可以选择+点击变量value,它会让你知道什么类型的编译器已经确定它是。在这种情况下,value是类型T即使我指定items[Array<U.ModelType>]。他们应该是相同的,因为T == U.ModelType,但由于某些原因,它不能在子类编译过程中弄清楚。

根据你的想法,虽然我认为T并不是真的必要,因为你正在形成U和T之间的关系。简单地提供U作为通用参数应该是足够的,就像我的第一个代码块一样。

+0

嘿艾伦,这是一个伟大的答案,它肯定解决问题,谢谢!我很想知道是否有其他人能够在我的原始示例中提供编译器行为的解释,因此我会等待几天,然后再将您的答案标记为已接受。再次感谢,我感谢您抽出时间仔细研究它! – Rog

+0

我也很感兴趣。 –

+1

@Rog踢我把你的代码在Xcode 9B6,它编译和运行完美,所以它看起来就像是已经固定的编译器错误。 –