静态协议扩展生成非法指令编译器错误

时间:2015-06-20 08:18:14

标签: swift protocols swift-extensions

我已阅读Swift中提供的Extensions,并想知道是否支持静态protocol extensions?我知道实例方法可以在protocol extension中使用。

我想为我的存储库创建一个协议,以及该存储库的实现:

存储库协议

public protocol NoteRepositoryProtocol {
    func getAllNotes() -> [Note]
}

存储库实现

class NoteRepository : NoteRepositoryProtocol {
    func getAllNotes() -> [Note] {
        return [Note]()
    }
}

然后为了在我的应用程序中保持松耦合,我想通过工厂创建存储库。我试图变得聪明并将静态方法附加到我的协议中,如下所示:

public extension NoteRepositoryProtocol {
    public static func createInstance() -> NoteRepositoryProtocol {
        return NoteRepository()
    }
}

我知道如果我在此处删除static关键字,可以这样做,但我真的希望它是静态的,所以我可以这样做:

func test_note_repository_returns_a_valid_note_repository() {
    let repository = NoteRepositoryProtocol.createInstance()
}

现在,当我想更改我的存储库实现时,我可以通过更新我的协议扩展工厂方法来实现。另一种方法是创建一个实际工厂来处理这个问题,但我喜欢在类型本身上存在工厂方法的想法。

当我编译它时,我得到以下编译器错误:

  

命令因信号失败:非法指令:4

     

警告:初始化不可变值'存储库'从未使用过;考虑更换为' _'或删除它           let repository = NoteRepositoryProtocol.createInstance()           ~~~~ ^ ~~~~~~~~~           _   不存在   无法执行的执行   /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-700.0.38.1/src/swift/lib/SILGen/SILGenExpr.cpp:3311!   0 swift 0x0000000106760e0b llvm :: sys :: PrintStackTrace(__ sFILE *)+ 43   1 swift 0x000000010676154b SignalHandler(int)+ 379   2 libsystem_platform.dylib 0x00007fff9440ef1a _sigtramp + 26   3 swift 0x0000000106d5aa2e FirstTarget + 60550   4 swift 0x0000000106761346 abort + 22   5 swift 0x000000010671ae21 llvm :: llvm_unreachable_internal(char const *,char const *,unsigned int)+ 481   6 swift 0x00000001049b503c swift :: Lowering :: SILGenFunction :: emitOpenExistentialImpl(swift :: OpenExistentialExpr *,llvm :: function_ref)+ 2588   7 swift 0x00000001049c0ba1 swift :: Lowering :: RValue swift :: Lowering :: SILGenFunction :: emitOpenExistential(swift :: OpenExistentialExpr *,(匿名命名空间):: RValueEmitter :: visitOpenExistentialExpr(swift :: OpenExistentialExpr *,swift :: Lowering :: SGFContext):: $ _ 0)+ 65   8 swift 0x00000001049b6f00 swift :: ASTVisitor<(匿名命名空间):: RValueEmitter,swift :: Lowering :: RValue,void,void,void,void,void,swift :: Lowering :: SGFContext> :: visit(swift :: Expr *,swift :: Lowering :: SGFContext)+ 4864   9 swift 0x00000001049af49f swift :: Lowering :: SILGenFunction :: emitExprInto(swift :: Expr *,swift :: Lowering :: Initialization *)+ 303   10 swift 0x00000001049a0dd8 swift :: Lowering :: SILGenFunction :: visitPatternBindingDecl(swift :: PatternBindingDecl *)+ 232   11 swift 0x0000000104a021fa swift :: ASTVisitor<(匿名命名空间):: StmtEmitter,void,void,void,void,void,void> :: visit(swift :: Stmt *)+ 362   12 swift 0x0000000104a02085 swift ::降低:: SILGenFunction :: emitStmt(swift :: Stmt *)+ 21   13 swift 0x00000001049ca136 swift :: Lowering :: SILGenFunction :: emitFunction(swift :: FuncDecl *)+ 390   14 swift 0x000000010496d3ed swift :: Lowering :: SILGenModule :: emitFunction(swift :: FuncDecl *)+ 253   15 swift 0x0000000104a0833c(匿名命名空间):: SILGenType :: emitType()+ 956   16 swift 0x0000000104a07ede swift :: Lowering :: SILGenModule :: visitNominalTypeDecl(swift :: NominalTypeDecl *)+ 30   17 swift 0x000000010497028b swift :: Lowering :: SILGenModule :: emitSourceFile(swift :: SourceFile *,unsigned int)+ 571   18 swift 0x000000010497106f swift :: SILModule :: constructSIL(swift :: ModuleDecl *,swift :: SILOptions&,swift :: FileUnit *,llvm :: Optional,bool,bool)+ 703   19 swift 0x000000010497128b swift :: performSILGeneration(swift :: FileUnit&,swift :: SILOptions&,llvm :: Optional,bool)+ 123   20 swift 0x000000010477a691 performCompile(swift :: CompilerInstance&,swift :: CompilerInvocation&,llvm :: ArrayRef,int&)+ 9153   21 swift 0x00000001047780b3 frontend_main(llvm :: ArrayRef,char const *,void *)+ 2515   22 swift 0x000000010477428f main + 1983   23 libdyld.dylib 0x00007fff934fb5c9 start + 1   24 libdyld.dylib 0x0000000000000048 start + 1823492736

您是否可以在协议扩展中使用静态方法?

更新

我删除了单元测试断言,以改进示例源中问题的根源。问题是编译器不喜欢我在协议上调用静态方法。

2 个答案:

答案 0 :(得分:1)

非可选永远不能为零

public static func createInstance() -> NoteRepositoryProtocol? {
    return NoteRepository()
}

答案 1 :(得分:0)

正如Apple Documentation

中所述
  

协议实际上并不实现任何功能。   尽管如此,您创建的任何协议都将成为完全成熟的类型   用于您的代码。

因此,您无法直接调用协议的静态方法。