Swift泛型类实现泛型函数时类型转换错误求助
泛型类与泛型函数类型冲突错误分析
错误信息
Cannot convert return expression of type 'Model' to return type 'Model'
问题代码
泛型类代码
public class URLCacheAdapter<Model>:LoaderProtocol{ public let adaptee:URLCache public let mapper: (Data,URLResponse) throws -> Model public typealias Mapper = (Data,URLResponse) throws -> Model public init(adaptee: URLCache, mapper: @escaping (Data,URLResponse) throws -> Model) { self.adaptee = adaptee self.mapper = mapper } public enum CacheErrors:Swift.Error{ case dataNotFound } public func load<Model>() async throws -> Model { guard let cachedResponse = adaptee.cachedResponse(for: requet) else{ throw CacheErrors.dataNotFound } return mapper(cachedResponse.data,cachedResponse.response) // Error here } }
协议代码
public protocol LoaderProtocol{ func load<T>() async throws -> T }
泛型映射器代码
public class DataMapper{ public enum Errors: Error{ case invalidData } public static func map(_ data:Data,from response:HTTPURLResponse) throws -> People{ guard response.statusCode == 200, let root = try? JSONDecoder().decode(PeopleModel.self, from: data) else{ throw Errors.invalidData } return ConvertModelToDto.convertToPeopleData(model: root) } }
问题原因
- 泛型重名冲突:类的泛型参数
Model和load函数的泛型参数Model是完全独立的两个类型。类的Model由初始化时传入的mapper决定,而函数的Model是调用时指定的任意类型,编译器无法将两者关联,导致返回值类型不匹配。 - 协议与类的泛型不兼容:原
LoaderProtocol要求load函数能返回任意类型<T>,但URLCacheAdapter类只能返回固定的Model类型,违背了协议要求,进一步加剧类型冲突。 - 拼写错误:代码中
requet是request的拼写错误,会导致未定义变量问题。
解决方案
1. 修改协议为泛型协议
让协议关联具体类型,匹配类的泛型:
public protocol LoaderProtocol { associatedtype Model func load() async throws -> Model }
2. 修正泛型类的load函数
移除函数的泛型参数,直接使用类级别的泛型Model,同时修正拼写错误:
public class URLCacheAdapter<Model>: LoaderProtocol { public let adaptee: URLCache public let mapper: (Data, URLResponse) throws -> Model public let request: URLRequest public typealias Mapper = (Data, URLResponse) throws -> Model public init(adaptee: URLCache, request: URLRequest, mapper: @escaping (Data, URLResponse) throws -> Model) { self.adaptee = adaptee self.request = request self.mapper = mapper } public enum CacheErrors: Swift.Error { case dataNotFound } public func load() async throws -> Model { guard let cachedResponse = adaptee.cachedResponse(for: request) else { throw CacheErrors.dataNotFound } return try mapper(cachedResponse.data, cachedResponse.response) } }
3. 映射器使用示例
DataMapper的map函数返回固定People类型,初始化URLCacheAdapter时直接传入即可:
let cache = URLCache.shared let request = URLRequest(url: URL(string: "your-target-url")!) let adapter = URLCacheAdapter<People>(adaptee: cache, request: request) { data, response in guard let httpResponse = response as? HTTPURLResponse else { throw DataMapper.Errors.invalidData } return try DataMapper.map(data, from: httpResponse) }
内容的提问来源于stack exchange,提问作者Tushar Sharma
相关产品推荐
相关产品推荐

