2015-01-05 44 views
3

我使用的擴展與像類方法的現有類嘗試:如何在帶有泛型的Swift擴展中使用帶可選類方法的協議?

@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說:「命令/應用程序/ Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc失敗,退出代碼1」。如果我在協議中不使用「可選」,我不需要在擴展中解開foo(),即使刪除「self」,一切都可以正常工作。任何人都可以告訴我爲什麼以及如何使可選工作正確嗎? 在此先感謝。

回答

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強制轉換,因爲如果您試圖直接撥打p上的.dynamicType.foo?(),您將獲得「訪問協議類型值'MyProtocol.Type'的成員未實現」。如果通用版本的崩潰與此相關,我不會感到驚訝。

我還會說,它值得問自己,你是否真的需要一個帶可選方法的協議(特別是類級別的協議),以及是否有一種方法可以完全靜態地使用泛型(因爲你已經半做)。

+0

關於此的實際代碼要複雜得多。這是我如何優化與路由器一起使用Alamofire的設計。可以不使用可選的(只是一些額外的行),但問題真的讓我困惑。謝謝你的解釋! – Wizard

相關問題