// MARK: - Third Party Library
public protocol TestProtocol: ExpressibleByStringLiteral {
init(str: String)
}
extension TestProtocol {
public init(stringLiteral value: String) {
self.init(str: value)
}
}
public struct Test {
public let str: String
public init(str: String) {
self.str = str
}
}
extension Test: TestProtocol {}
// MARK: - My Swift Package
extension Test {
public init(stringLiteral value: String) {
self.init(str: "Roman")
}
}
let test: Test = "Test"
print(test.str)
这是游乐场友好的代码片段,它按预期工作。我将重写初始化程序,以便无论我们真正分配什么,代码总是打印“Roman”。
但是,一旦我将“第三方库”代码移至游乐场的“源”文件夹(以模仿第三方库的使用),行为就会发生变化:我的重写方法被忽略😣
这不可能。两个模块分别编译,当
编译后,编译器需要生成 的协议见证表,
Test
以保证 的一致性TestProtocol
。该表主要存储了哪些事物Test
实现了哪些要求TestProtocol
。不知道某种类型的具体类型的调用者TestProtocol
将使用此表来查找他们应该调用的实际实现,例如尽管编译器可以直接转换
let test: Test = "Test"
为let test: Test = Test(stringLiteral: "Test")
(这将init
在Test
扩展中调用 ),但它被实现为调用 的协议见证ExpressibleByStringLiteral.init(stringLiteral:)
。当生成协议见证表时,编译器显然不会看到你在 中声明的那个
extension Test
,因为这些文件是单独编译的。当然,如果编译器看到 中声明的实现
extension Test
,它会选择该实现而不是默认实现。因此,图书馆之外的任何事物都无法改变
let test: Test = "Test"
现状。