子类化泛型类

时间:2017-08-31 01:51:27

标签: swift generics

我正在尝试在Swift中继承一个泛型类,但无论我做什么,编译器都会抱怨,或者更糟糕的是,segfaulting。

这是我编写它的最接近的,但后来我无法创建子类的实例,因为编译器由于某种原因无法推断出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 个答案:

答案 0 :(得分:1)

这里有很多东西,非常简单的Swift类型系统。但是,这是你想要的吗?

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作为通用参数就足够了,就像在我的第一个代码块。