Swift 遵循多协议时&符号与逗号的用法区别
Swift 中多协议声明的逗号与&核心差异
二者本质是完全不同场景下的语法,你在Playground测试时部分场景表现一致,只是编译器做了兼容处理,官方语法规则里二者的适用边界非常清晰:
逗号:约束/遵循列表的分隔符
逗号是用来分隔多个独立声明项的语法,仅能用在「罗列多个要求」的位置,不能用来表示一个具体类型,适用场景包括:
- 定义自定义类型(类、结构体、枚举)时,在类型名后的冒号后,分隔父类和需要遵循的多个协议
// 规范写法,此处必须用逗号 struct Person: Named, Aged { var name: String var age: Int } - 泛型参数的约束列表中,分隔多个对泛型类型的独立要求
// 泛型约束处用逗号分隔多个遵循要求 func wishHappyBirthday<T: Named, Aged>(to celebrator: T) { print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!") } - 扩展的where子句中,分隔多个匹配约束
// where约束中多个并列条件用逗号分隔 extension Array where Element: Named, Element: Aged { func sayBirthdayWishes() { forEach { print("Happy birthday, \($0.name), you're \($0.age)!") } } }
&:协议组合运算符
&的作用是将多个协议(或一个父类+多个协议)合并为一个单一的匿名组合类型,仅能用在「需要填写具体类型名」的位置,不能用来罗列约束,适用场景包括:
- 函数/方法的参数类型、返回值类型标注
// 参数位置需要传入一个具体类型,必须用&拼接组合类型,此处用逗号会直接报错 func wishHappyBirthday(to celebrator: Named & Aged) { print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!") } - 变量/常量的显式类型标注
// 声明变量类型时,用&表示组合类型 let celebrator: Named & Aged = Person(name: "Malcolm", age: 21) - 类型判断/转换(
is/as/as?/as!)的目标类型// 类型转换的目标是单个组合类型,用&拼接 if let person = someValue as? Named & Aged { print("Find a valid celebrator: \(person.name)") }
为什么测试时会感觉二者可以通用?
当前Swift编译器对非规范写法做了单向兼容:如果你在类型遵循声明的位置写struct Person: Named & Aged,编译器会自动把组合类型拆解为「同时遵循Named、Aged两个协议」的要求,运行效果和写逗号完全一致。但反过来,如果你在需要写类型的位置用逗号分隔多个协议(比如把参数类型写成Named, Aged),编译器会直接抛出语法错误,不存在兼容。
使用建议
- 所有罗列遵循要求、约束项的场景,统一使用逗号,这是官方规范写法,不会有版本兼容问题
- 所有需要表示一个「同时满足多个协议要求的类型」的场景,统一使用&做协议组合
- 不要在类型遵循声明的位置写&组合语法,这类非规范写法可能在未来Swift版本的语法收紧中失效。
内容的提问来源于stack exchange,提问作者praivis
相关产品推荐
相关产品推荐

