【问题标题】:Why doesn't this behave the way I expect (hope) it would?为什么这不符合我的预期(希望)?
【发布时间】:2018-04-19 15:10:31
【问题描述】:

我在我的框架中设置了几个协议来处理资源。在其中一个协议中,我设置了一个扩展来为decode 函数提供默认实现。显示代码和发生的情况更简单(请参阅对fatalError 的调用)。实际实现中还有很多代码,但这说明了问题:

这是“基本”协议:

public protocol Resourceful {
    associatedtype AssociatedResource
    typealias ResourceCompletionHandler = (AssociatedResource?, Error?) -> Void

    func fetch(_ completion: @escaping ResourceCompletionHandler)
}

这是一个通用的、具体的 Resourceful 实现:

    open class WebResourceApiCall<Resource>: Resourceful {
    public typealias AssociatedResource = Resource
    public typealias FetchedResponse = (data: Data?, urlResponse: URLResponse?)

    public init() {
    }

    public func fetch(_ completion: @escaping ResourceCompletionHandler) {
        try! decode(fetched: (data: nil, urlResponse: nil))
    }

    public func decode(fetched: FetchedResponse) throws -> Resource {
        fatalError("It ends up here, but I don't want it to!")
    }
}

extension WebResourceApiCall where Resource: Decodable {
    public func decode(fetched: FetchedResponse) throws -> Resource {
        fatalError("This is where I want it to go...")
    }
}

这就是我尝试使用它的方式:

public struct Something: Decodable { }

var apiCall = WebResourceApiCall<Something>()
apiCall.fetch { _, _ in } // Implictly calls decode... but not the decode I expected it to! See fatalError() calls...

不会像我希望的那样在扩展程序上调用decode,而是始终调用没有约束的“默认”decode 方法。

为什么这不符合我的预期?

提前致谢!

【问题讨论】:

    标签: swift generics swift-protocols


    【解决方案1】:

    Swift 是一种静态调度语言,因此要调用的 decode() 函数的地址是在编译时计算的,并且由于调用发生在类的基本定义中,编译器会选择原始实现。

    现在,如果您从编译器有足够信息选择您需要的实现的地方调用该方法,它将起作用:

    var apiCall = WebResourceApiCall<Something>()
    try apiCall.decode(fetched: (nil, nil))
    

    上面的代码将从专门的扩展中调用方法,因为此时编译器可以更好地知道它有一个更专门的实现要调用。

    如果您在动态调度世界中移动 decode() 方法(即在协议级别),应该可以实现您需要的行为。

    【讨论】:

      猜你喜欢
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-18
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 1970-01-01
      相关资源
      最近更新 更多