为什么Swift编译器无法推断类型?

时间:2018-11-15 07:26:40

标签: swift

我已经开发了这种通用方法来执行请求:

func executeRequest<T, S, E>(_ request : RequestBuilder<T>,
                             map: (@escaping (T) -> S)) -> RepositoryResult<S, E> {
    return RepositoryResult().doTask { result in
        request.execute{ (response, error) in
            // do some stuff
            result.notifySuccess(value: map(body))
        }
}

我的地图函数是在具有通用类型的子类中定义的:

class BaseMapper<R, U> {
    class func transform(_ dataModel:R) -> U {
        fatalError("Override this method")
    }
    // other generic methods
}

class HomeMapper:BaseMapper<HomeDTO, Home> {
    override class func transform(_ dataModel: HomeDTO) -> Home {
        return Home(customerFirstName: dataModel.customerFirstName,
                balance: MoneyMapper.transform(dataModel.balance),
                accounts: AccountSummaryMapper.listTransform(dataModel.summaries))
    }
}

如果我调用请求执行程序方法,则直接传递map函数,如下所示:

 func getHomeInfo() -> RepositoryResult<Home, HomeError> {
    return executeRequest(HomeAPI.getMyHomeWithRequestBuilder(), map: HomeMapper.transform)
 }

我相信Swift编译器会崩溃,因为它会返回几个随机错误:“细分错误:11”。否则,如果我调用指定“ S”返回类型的方法,它将起作用:

func getHomeInfo() -> RepositoryResult<Home, HomeError>{
    return executeRequest(HomeAPI.getMyHomeWithRequestBuilder(), map: { (homeDTO) -> Home in
        HomeMapper.transform(homeDTO)
    })
} 

此外,使用不继承自BaseMapper的Mapper并直接传递函数,它也可以工作。我不明白的另一件事是RxSwift有一个map函数,可以使用我的第一个选项调用它...

为什么Swift编译器无法推断“ S”类型?为什么Swift编译器崩溃了,却无法分辨哪一行崩溃了,为什么?

1 个答案:

答案 0 :(得分:0)

我找到了一个解决方案:associatedtypes

protocol Mappable {
    associatedtype T
    associatedtype S

    static func transform(_ dataModel:T) -> S
}

class MapperHome : Mappable {
    static func transform(_ dataModel: HomeDTO) -> Home {
        return Home(customerFirstName: dataModel.customerFirstName,
                balance: MoneyMapper.transform(dataModel.balance),
                accounts: AccountSummaryMapper.listTransform(dataModel.summaries))
    }
}

func getHomeInfo() -> RepositoryResult<Home, HomeError>{
    return executeRequest(HomeAPI.getMyHomeWithRequestBuilder(), map: MapperHome.transform)
}

我不明白为什么这段代码会编译,并且使用协议实现的继承实例却没有...我不知道这是编译器错误还是我的错。