2016-12-01 42 views
5

考慮到有一個工廠方法的協議:協議是否可能具有靜態工廠方法的默認實現?

public protocol Frobnicator { 

    func frobnicate() 

    static func makeRightFrobnicator() -> Frobnicator 
} 

private class SomeFrobnicatorImplementation: Frobnicator { ... } 
private class AnotherFrobnicatorImplementation: Frobnicator { ... } 

public extension Frobnicator { 

    static func makeRightFrobnicator() -> Frobnicator { 
    if something { 
     return SomeFrobnicatorImplementation() 
    } else { 
     return AnotherFrobnicatorImplementation() 
    } 
    } 
} 

我希望能夠在不同的時間構造不同實施者。實現者本身對模塊是私有的,而協議在客戶端代碼中是公共的。

當我嘗試了上述類似的代碼,我得到「靜態成員makeRightFrobnicator不能在協議元類型Frobnicator.Protocol使用。」

有周圍沒有任何辦法,或者我應該只使用免費的功能?

+0

這是工廠模式的用途。 – Dai

+0

@戴,是的,雖然問題是關於我是否可以使用協議靜態方法的默認實現。 – Zomagk

+0

「問題是關於我是否可以使用協議靜態方法的默認實現」那麼你爲什麼不說這個問題呢?這不是關於具有靜態方法的協議。這是關於協議_extensions_提供_implementation_靜態方法。 – matt

回答

3

靜態功能的實現是合法的:

protocol P { 
    static func f() -> P 
    init() 
} 

extension P { 
    static func f() -> P {return self.init()} 
} 

但是你會發現,爲了得到它來編譯,我必須保證我手上有合法的方法,使編譯器P以便能夠返回一個。

您的代碼的問題是嘗試返回協議的特定採用者,如SomeFrobnicatorImplementation。對於誰採用它,協議是不可知的。換句話說,你不能保證在協議定義中SomeFrobnicatorImplementation實際上是這個協議的採用者。因此,你的部分代碼是非法的。

+0

我沒有讓你失望。我很欣賞這種努力,只是想補充一點,'return self.init()'不會編譯,而'return X()'奇怪的不會。 https://repl.it/Ecm0/1 https://repl.it/Ecm0/0 – Zomagk

+1

'return X.init()'。但前提是編譯器知道這是合法的。它不能成爲特定的P採納者,協議如何知道採納者是誰? – matt

+0

上面編譯,但是當試圖與'P.f()'使用它時,我得到錯誤消息「錯誤:靜態成員'f'不能用於協議元類型'P.Protocol'」。即使我的代碼改變爲這樣: 協議p { 靜態FUNC F() - >點 的init() } 延伸p { 靜態FUNC F() - > p {返回S.init() } } struct S:P { } Pf() – kareman