如何在Swift中使用泛型的扩展中使用带有可选类方法的协议?

时间:2015-01-05 12:22:50

标签: swift generics swift-extensions swift-protocols

我正在尝试使用类方法的现有类的扩展名:

@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失败,退出代码为1”。如果我不在协议中使用“可选”,我不需要在扩展中打开foo(),即使我删除了“self”,一切都运行良好。任何人都可以告诉我为什么以及如何使可选的工作正常? 提前谢谢。

1 个答案:

答案 0 :(得分:2)

看起来你在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强制转换,因为如果您尝试直接在.dynamicType.foo?()上调用p,则会“访问协议类型值'MyProtocol.Type'的成员未实现”。如果泛型版本的崩溃与此相关,我不会感到惊讶。

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