如何在带Swift泛型的扩展中使用可选类方法的协议? [英] How to use a protocol with optional class methods in an extension with generic in Swift?

查看:423
本文介绍了如何在带Swift泛型的扩展中使用可选类方法的协议?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  @objc public protocol MyProtocol {
可选类func foo() - > Int
}

我在扩展中使用这个协议, p>

  extension MyClass {

public func bar< T:MyProtocol>(){
.. 。
let x:Int = T.self.foo!()//如果我不使用self或!在这里,我将有一个编译器错误
...
}

应该可以工作,但是当我编译它时,Xcode会说命令/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc失败并退出代码1。如果我在协议中不使用可选,我不需要在扩展中解开foo(),即使删除self,一切都可以正常工作。任何人都可以告诉我为什么以及如何使可选工作正确吗?
在此先感谢。

解决方案

看起来您已经在Swift编译器中发现了一个(相当模糊的)错误这会导致它崩溃。
下面是在单个文件中需要的所有副本的崩溃 swiftc

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

(您不需要调用 f 它会崩溃)

您应该提交一个雷达,因为无论您的代码是什么,编译器崩溃都不会发生。



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



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


$ b $

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

(甚至可能有更好的方法,但我无法发现它)。



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



我也会说它值得问自己,你是否真的需要一个协议可选的方法(特别是类级别的方法)以及是否有办法完全静态地使用泛型(因为您已经半参与)。


I am trying using extension for an existing class with class method like:

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

And I am using this protocol in an extension with generic like:

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
        ...
    }

This should work but when I build it, Xcode says "Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1". If I do not use "optional" in the protocol, I do not need to unwrap the foo() in the extension and everything works well even if I remove the "self". Can anyone tell me why and how to make the optional work properly? Thanks in advance.

解决方案

It looks like you've found a (fairly obscure) bug in the Swift compiler that's causing it to crash. Here's a reproduction that's all you need in a single file to crash swiftc:

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

(you don't need to call f for it to crash)

You should probably file a radar since the compiler crashing is never expected behavior no matter what your code.

If you tried to do this without the optional, it'll work (and you can even ditch the self). My guess is the implementation of generics doesn't currently account for the possibility of optional class-level functions.

You can do it without generics like this:

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

(there may even be a better way but I can't spot it).

You need the AnyObject cast because if you try to call .dynamicType.foo?() on p directly you get "accessing members of protocol type value 'MyProtocol.Type' is unimplemented". I wouldn't be surprised if the crash of the generic version is related to this.

I'd also say that its worth asking yourself whether you really need a protocol with optional methods (especially class-level ones) and whether there's a way to do what you want entirely statically using generics (as you're already semi-doing).

这篇关于如何在带Swift泛型的扩展中使用可选类方法的协议?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆