代码之家  ›  专栏  ›  技术社区  ›  CZ54

使用通用协议作为接口

  •  4
  • CZ54  · 技术社区  · 6 年前

    我想创建一个 UseCase 协议,使用通用协议。然后我想为所有实现创建一个接口,以便为测试创建mock。

    struct Product {}
    
    protocol UseCase {
        associatedtype ReturnType
        associatedtype Param
        func execute(_ params: Param, completion: ((ReturnType) -> Void))
    }
    
    
    protocol FetchProductsUseCase: UseCase {
        associatedtype ReturnType = [Product]
        associatedtype Param = Void
    }
    
    
    struct FetchProductsUseCaseImpl: FetchProductsUseCase {
        func execute(_ params: Param , completion: ((ReturnType) -> Void)) {
            completion([])
        }
    }
    
    //ERROR: Protocol 'FetchProductsUseCase' can only be used as a generic constraint because it has Self or associated type requirements
    var useCase: FetchProductsUseCase!
    

    有人能帮我修一下吗?

    我搜索了SOF,找到了很多关于泛型的主题,但是没有一个对我的案例有帮助。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Daniel T.    6 年前

    所以没有办法“约束”fetchproductusecase只接受一对泛型即:Void/[产品]?

    FetchProductsUseCase 不是你怎么做的。请改为:

    struct AnyUseCase<P, R>: UseCase {
    
        typealias ReturnType = R
        typealias Param = P
    
        init<U>(useCase: U) where U: UseCase, U.ReturnType == ReturnType, U.Param == Param {
            _execute = useCase.execute
        }
    
        func execute(_ params: P, completion: ((R) -> Void)) {
            _execute(params, completion)
        }
    
        let _execute: (P, (R) -> Void) -> Void
    }
    
    var useCase: AnyUseCase<Void, [Product]>!
    

    然后你可以这样做:

    useCase = AnyUseCase(useCase: FetchProductsUseCaseImpl())
    

    我想你的下一个错误是 completion 不是逃跑。可能需要这样。