我目前正在为两个数据库API编写和数据库访问类(王国和Firestore)。为了精简代码,我尝试用泛型解决整个问题(#1)。不幸的是它不起作用了。我在哪里错过了重点?
我尝试定义关联类型(#2)并在RealmAccessStragy类中设置它们。但在这一点上,如果试图通过PersistenceController访问协议,编译器将返回错误。
我很感谢你的帮助!
方法#1
enum DataResult<T> {
case success(T)
case failure(Error)
}
protocol DataApiAccess: AnyObject {
func read<U, T>(primaryKey: U, completion: @escaping ((DataResult<T>) -> Void))
}
class RealmAccessStrategy {
...
func read<U, T>(primaryKey: U, completion: @escaping ((DataResult<T>) -> Void)) {
guard let realmObject = realmInstance.object(ofType: realmObjectType, forPrimaryKey: primaryKey) else {
completion(.failure(RealmAccessError.noObject))
return
}
completion(.success(realmObject)) // ERROR: Member 'success' in 'DataResult<_>' produces result of type 'DataResult<T>', but context expects 'DataResult<_>'
}
}
// Later implementation
class PersistenceController {
private let strategy: DataApiAccess
init(use: DataApiAccess) {
self.strategy = use
}
func load<U, T>(primaryKey: U, completion: @escaping ( (DataResult<T>) -> Void ) ) {
strategy.read(primaryKey: primaryKey, completion: completion)
}
}'DataResult<>‘中的错误:成员“成功”生成'DataResult’类型的结果,但上下文要求'DataResult<>'
方法#2
enum DataResult<T> {
case success(T)
case failure(Error)
}
protocol DataApiAccess {
associatedtype ReturnType
func read(primaryKey: PrimaryKeyType, completion: @escaping DataApiHandler<ReturnType>)
}
class RealmAccessStrategy: DataApiAccess {
...
// Typealias
internal typealias ReturnType = Object
func read(primaryKey: Any, completion: @escaping ((DataResult<Object>) -> Void)) {
guard let realmObject = realmInstance.object(ofType: realmObjectType, forPrimaryKey: primaryKey) else {
completion(.failure(RealmAccessError.noObject))
return
}
completion(.success(realmObject))
}
}
class PersistenceController {
private let strategy: DataApiAccess // ERROR: Protocol 'DataApiAccess' can only be used as a generic constraint because it has Self or associated type requirements
init(use: DataApiAccess) {
self.strategy = use
}
...
}
}错误:协议'DataApiAccess‘只能用作泛型约束,因为它具有自或关联类型需求
发布于 2019-07-23 14:50:57
不能设置变量泛型协议,但可以设置方法
示例代码在下面
///Set a protocol generic methods:
protocol DataApiAccess {
func read<T: Codable>(primaryKey: PrimaryKeyType, completion: @escaping (DataResult<T>) -> Void)
}
class RealmAccessStrategy: DataApiAccess {
func read<T: Codable>(primaryKey: PrimaryKeyType, completion: @escaping (DataResult<T>) -> Void) {
// Read data from database
}
}
class NetworkAccessStrategy: DataApiAccess {
func read<T: Codable>(primaryKey: PrimaryKeyType, completion: @escaping (DataResult<T>) -> Void) {
// Get data from request
}
}
class PersistenceController {
private let strategy: DataApiAccess
init(use: DataApiAccess) {
// Set dependency inversion for offline or online state
self.strategy = use
}
func foo() {
// TODO
//strategy.read(primaryKey: <#T##PrimaryKeyType#>, completion: <#T##(DataResult<Decodable & Encodable>) -> Void#>)
}
}享受吧!
https://stackoverflow.com/questions/57166352
复制相似问题