Swift返回协议类型的函数能否嵌套调用?文档与实测不符疑问
在SwiftUI开发中学习协议与不透明类型时,看到《The Swift Programming Language》官方文档说明:返回Shape协议类型的protoFlip(_:)函数无法嵌套调用,因为协议类型的值并不遵循该协议,protoFlip返回的结果无法作为参数传入自身。但实际在Playground中测试以下代码时,protoFlip(protoFlip(smallTriangle))却能正常运行:
protocol Shape { func draw() -> String } struct Triangle: Shape { var size: Int func draw() -> String { var result: [String] = [] for length in 1...size { result.append(String(repeating: "*", count: length)) } return result.joined(separator: "\n") } } // 返回类型为协议 func protoFlip<T: Shape>(_ shape: T) -> Shape { if shape is Square { return shape } return FlippedShape(shape: shape) } // 测试嵌套调用 let smallTriangle = Triangle(size: 3) let testNest = protoFlip(protoFlip(smallTriangle))
这种情况并非文档错误,而是Swift版本更新带来的行为变化:
旧版本Swift的限制
文档中描述的“协议类型的值不遵循该协议”是Swift 5.7之前的行为。当时,函数返回的Shape协议类型(存在类型)无法传入要求<T: Shape>的protoFlip(_:)函数,因为存在类型本身不被视为遵循对应的协议。Swift 5.7的特性更新
从Swift 5.7开始,语言引入了存在类型的隐式一致性:对于没有关联类型、Self约束等限制的协议(比如你定义的Shape协议),协议类型的存在值会被隐式视为遵循该协议,因此可以直接传入要求遵循该协议的泛型参数。代码可运行的原因
你使用的Playground基于Swift 5.7或更高版本,因此内层protoFlip返回的Shape存在类型值,会被隐式转换为符合Shape协议的具体类型实例,满足外层函数的泛型约束,嵌套调用得以正常执行。
注意:如果Shape协议包含关联类型或Self相关约束,即使在Swift 5.7+中,这种嵌套调用仍然会失败,因为这类协议的存在类型无法隐式符合自身。
内容的提问来源于stack exchange,提问作者justPassingBy

