You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让类复用带默认实现的泛型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方法,如何修改才能复用默认实现?

问题原因

  1. 协议定义的方法是getall()(全小写),但默认实现的是getAll()(驼峰命名),二者是不同方法,协议要求的方法没有默认实现,因此必须手动编写。
  2. SomeDBService实现协议时未明确指定关联类型T,默认实现无法推断T的具体类型。
  3. 默认实现中直接新建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:42:52