代码之家  ›  专栏  ›  技术社区  ›  J. Doe

动态调度协议扩展不适用于多个目标

  •  2
  • J. Doe  · 技术社区  · 6 年前

    这是我的主要目标中的代码(因此不是测试目标):

    protocol ProtocolA {
        func dontCrash()
    }
    
    extension ProtocolA {
        func dontCrash() {
            fatalError()
        }
    
        func tryCrash() {
            dontCrash()
        }
    }
    
    class MyClass: ProtocolA {}
    

    在我的测试目标(如此不同的目标)中,我得到了以下代码:

    import XCTest
    @testable import Project
    
    extension MyClass {
        func dontCrash() {
            print("I dont crash")
        }
    }
    
    class ProjectTests: XCTestCase {
        func testExample() {
            MyClass().tryCrash()
        }
    }
    

    MyClass dontCrash() ,我想那只会开火。

    1 回复  |  直到 6 年前
        1
  •  1
  •   rob mayoff    6 年前

    你的 Project MyClass 符合 ProtocolA .

    Swift使用一种称为协议见证表的数据结构来实现这种一致性。对于协议声明的每个方法,见证表包含一个函数,该函数调用一致性类型的方法的实际实现。

    具体而言,有一个见证表,证明 类名 原可乐 dontCrash 声明的方法 . 见证表中的函数调用 顿皮疹 方法。

    当测试用例命中时,您可以从堆栈跟踪中的协议见证表中看到函数 fatalError :

    #8  0x00000001003ab9d9 in _assertionFailure(_:_:file:line:flags:) ()
    #9  0x00000001000016fc in ProtocolA.dontCrash() at /Users/rmayoff/TestProjects/Project/Project/AppDelegate.swift:11
    #10 0x0000000100001868 in protocol witness for ProtocolA.dontCrash() in conformance MyClass ()
    #11 0x000000010000171e in ProtocolA.tryCrash() at /Users/rmayoff/TestProjects/Project/Project/AppDelegate.swift:15
    #12 0x00000001030f1987 in ProjectTests.testExample() at /Users/rmayoff/TestProjects/Project/ProjectTests/ProjectTests.swift:12
    #13 0x00000001030f19c4 in @objc ProjectTests.testExample() ()
    

    第10帧是来自 tryCrash 顿皮疹 .

    Swift在声明一致性的模块中发出协议见证表。所以,在你的情况下,证人表是 项目 模块。

    顿皮疹 项目 模块。

    这就是为什么必须这样做:

    假设我是这本书的作者 项目 模块,而您只是它的用户。当我写下 项目 模块,我知道你在打电话 MyClass().dontCrash() 会叫 致命错误 ,我依靠这种行为。在里面的很多地方 项目 ,我打电话 特别是因为我知道它会打电话来 致命错误 . 您,作为 项目 项目 这取决于你的行为。

    现在你使用 模块,但您可以追溯更改 不打电话 致命错误 . 现在所有这些地方 项目 电话 MyClass().dontCrash() 模块。你弄坏了门 项目 项目 模块或任何 项目 进口。

    这对机器的正确操作至关重要 项目 我们希望这种情况不会发生。那么改变的唯一方法是什么 MyClass().dontCrash() 指(从内部调用时) 项目 项目 项目 进口)。