Search code examples
swiftgenericsprotocols

How can I implement a generic class that conforms to a protocol with associated type?


Following swift code gives the Protocol 'DataSource' can only be used as a generic constraint because it has Self or associated type requirements error. How can it be fixed?

protocol DataSource {
    associatedtype DataItem
    func getItem(at index: Int) -> DataItem
}

struct DataSourceAgent: DataSource {
    typealias DataItem = Int
    func getItem(at index: Int) -> DataItem {
        return 0
    }
}

class SomeClass<T> {
    private var dataSource: DataSource!
    init(dataSource: DataSource) {
        self.dataSource = dataSource
    }
    func getSomeStuff() -> T {
        return dataSource.getItem(at: 0)
    }
}

let sc = SomeClass<Int>(dataSource: DataSourceAgent())

Snapshot of errors from playground


Solution

  • You can't use a protocol with associated type the same way as you would use normal protocol, but you can use DataSource as type constraint in SomeClass in this way:

    class SomeClass<T, D:DataSource> where D.DataItem == T {
        private let dataSource:D
    
        init(dataSource: D) {
            self.dataSource = dataSource
        }
        func getSomeStuff() -> T {
            return dataSource.getItem(at: 0)
        }
    }
    
    let sc = SomeClass<Int, DataSourceAgent>(dataSource: DataSourceAgent())
    print(sc.getSomeStuff())