【问题标题】:How to use a protocol with optional class methods in an extension with generic in Swift?如何在 Swift 中的泛型扩展中使用带有可选类方法的协议?
【发布时间】:2015-01-05 12:22:49
【问题描述】:

我正在尝试使用具有类方法的现有类的扩展,例如:

@objc public protocol MyProtocol {
    optional class func foo() -> Int
}

我在一个扩展中使用这个协议,比如:

extension MyClass {

    public func bar<T: MyProtocol>() {
        ...
        let x: Int = T.self.foo!() // if I do not use "self" or "!" here, I will have a compiler error
        ...
    }

这应该可以,但是当我构建它时,Xcode 说“Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1”。如果我不在协议中使用“可选”,我不需要在扩展中解开 foo() 并且即使我删除了“self”,一切都会正常工作。谁能告诉我为什么以及如何使可选功能正常工作? 提前致谢。

【问题讨论】:

    标签: swift generics swift-extensions swift-protocols


    【解决方案1】:

    您似乎在 Swift 编译器中发现了一个(相当模糊的)错误,导致它崩溃。 这是您在单个文件中崩溃所需的全部复制swiftc

    import Foundation
    @objc protocol P { optional class func f() }
    func f<T: P>(t: T) { T.self.f?() }
    

    (您无需调用f 即可使其崩溃)

    您可能应该提交一个雷达,因为无论您的代码是什么,编译器崩溃都不是预期的行为。

    如果您尝试在没有optional 的情况下执行此操作,它会起作用(您甚至可以放弃self)。我的猜测是泛型的实现目前没有考虑到可选类级函数的可能性。

    你可以在没有泛型的情况下这样做:

    func f(p: MyProtocol) {
        (p as AnyObject).dynamicType.foo?()
    }
    

    (甚至可能有更好的方法,但我找不到)。

    您需要AnyObject 演员,因为如果您尝试直接在p 上调用.dynamicType.foo?(),您会得到“访问协议类型值'MyProtocol.Type' 的成员未实现”。如果通用版本的崩溃与此有关,我不会感到惊讶。

    我还要说,值得问问自己是否真的需要一个带有可选方法(尤其是类级别的方法)的协议,以及是否有一种方法可以使用泛型完全静态地做你想做的事情(因为你已经是半- 做)。

    【讨论】:

    • 关于这个的实用代码要复杂得多。这就是我如何优化使用 Alamofire 和路由器的设计。不使用 optional 是可以的(只是多出几行),但这个问题真的让我很困惑。谢谢你的解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多