I have a mapper as follows
protocol MapperProtocol {
associatedtype T
associatedtype U
func map(item: T) -> U?
}
And I want to inject it to a class as follows
protocol ParserProtocol {
associatedtype T
associatedtype U
func parse(from: T) -> U?
}
class TrackParser: ParserProtocol {
typealias T = String
typealias U = Track
private let mapper: MapperProtocol
init(mapper: MapperProtocol) {
self.mapper = mapper
}
func parse(from path: String) -> Track? {
guard let data = try? Data(contentsOf: URL(filePath: path)) else { return nil }
return mapper.map(item: data)
}
}
TrackParser
will be initialised from somewhere else so it doesn't need to know the concrete type of the mapper.
When I want to implement it that way I get the following error. Any ideas how to fix it?
CodePudding user response:
Notice that the parse
implementation requires that the mapper has T == Data
and U == Track
, but you haven't specified those constraint anywhere in TrackParser
.
We can make T
and U
the primary associated types of MapperProtocol
, so that the same-type requirements can be specified very easily as MapperProtocol<Data, Track>
.
protocol MapperProtocol<T, U> { // Notice the "<T, U>"
associatedtype T
associatedtype U
func map(item: T) -> U?
}
Also, starting from Swift 5.7, existential types are required to be prefixed with "any
", so you would write:
private let mapper: any MapperProtocol<Data, Track>
init(mapper: any MapperProtocol<Data, Track>) {
self.mapper = mapper
}