如何让类复用带默认实现的泛型GetAllDBServiceProtocol?
如何让SomeDBService复用GetAllDBServiceProtocol的默认实现
问题背景
现有基础代码如下:
import Foundation import RealmSwift protocol GetAllDBServiceProtocol { associatedtype T: Object func getall() -> [T] } extension GetAllDBServiceProtocol { func getAll() -> [T] { DBStorageService().fetch(by: T.self) } } class DBStorageService { private let storage: Realm? init( _ configuration: Realm.Configuration = Realm.Configuration() ) { self.storage = try? Realm(configuration: configuration) } func fetch<T: Object>(by type: T.Type) -> [T] { guard let storage else { return [] } return storage.objects(T.self).toArray() } }
注:此RealmSwift使用方式可能不规范,但与当前问题无关。
尝试实现返回具体Realm对象数组的服务类:
class SomeDBService { private let storage: DBStorageService init(storage: DBStorageService) { self.storage = storage } } extension SomeDBService: GetAllDBServiceProtocol { func getall() -> [SomeDBEntity] { DBStorageService().fetch(by: SomeDBEntity.self) } }
当前问题:该代码可运行,但无法访问GetAllDBServiceProtocol的默认实现,必须自行实现getall方法,如何修改才能复用默认实现?
问题原因
- 协议定义的方法是
getall()(全小写),但默认实现的是getAll()(驼峰命名),二者是不同方法,协议要求的方法没有默认实现,因此必须手动编写。 SomeDBService实现协议时未明确指定关联类型T,默认实现无法推断T的具体类型。- 默认实现中直接新建
DBStorageService实例,未使用SomeDBService中注入的storage,既不符合依赖注入设计,也导致实例复用失效。
解决方案
步骤1:统一协议方法名
将协议中的方法名改为驼峰式,与默认实现保持一致:
protocol GetAllDBServiceProtocol { associatedtype T: Object func getAll() -> [T] // 修正方法名 }
步骤2:添加协议属性要求
为让默认实现能访问到实现类中的storage,在协议中添加只读属性要求:
protocol GetAllDBServiceProtocol { associatedtype T: Object var storage: DBStorageService { get } // 添加属性要求 func getAll() -> [T] }
步骤3:修改默认实现逻辑
让默认实现使用协议要求的storage属性,而非新建实例:
extension GetAllDBServiceProtocol { func getAll() -> [T] { storage.fetch(by: T.self) // 使用注入的storage } }
步骤4:完善SomeDBService的协议实现
在SomeDBService的协议扩展中明确指定关联类型T,并确保storage属性满足协议的只读要求:
class SomeDBService { let storage: DBStorageService // 改为let,满足协议的get要求 init(storage: DBStorageService) { self.storage = storage } } extension SomeDBService: GetAllDBServiceProtocol { typealias T = SomeDBEntity // 指定关联类型 }
最终完整代码
import Foundation import RealmSwift protocol GetAllDBServiceProtocol { associatedtype T: Object var storage: DBStorageService { get } func getAll() -> [T] } extension GetAllDBServiceProtocol { func getAll() -> [T] { storage.fetch(by: T.self) } } class DBStorageService { private let storage: Realm? init( _ configuration: Realm.Configuration = Realm.Configuration() ) { self.storage = try? Realm(configuration: configuration) } func fetch<T: Object>(by type: T.Type) -> [T] { guard let storage else { return [] } return storage.objects(T.self).toArray() } } class SomeDBService { let storage: DBStorageService init(storage: DBStorageService) { self.storage = storage } } extension SomeDBService: GetAllDBServiceProtocol { typealias T = SomeDBEntity }
修改后,SomeDBService可直接复用协议的默认实现,无需手动编写getAll()方法。
内容的提问来源于stack exchange,提问作者Gargo
相关产品推荐
相关产品推荐

