2016-12-01 121 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