Swift协议扩展中Self关键字与some Numeric返回类型的区别
Numeric扩展中Self与some Numeric的区别解析
先看你给出的原代码:
extension Numeric { func squared() -> Self { self * self } }
针对你的三个疑问,逐一解答:
1. 能不能把返回类型的Self替换成some Numeric?
不行,直接替换会触发编译错误。原因是Numeric协议包含关联类型(比如Magnitude),这类协议不能直接作为具体类型使用;而some Numeric作为不透明返回类型,要求函数返回的具体类型在编译期是固定的——但这个扩展是给所有遵循Numeric的类型(Int、Double、Float等)添加方法,不同类型调用squared()时返回的具体类型是各自的原类型,无法用单一的不透明类型统一。
2. 编译器调用squared()时能否推断具体类型?
如果硬写some Numeric作为返回类型,编译器无法推断出调用者的原具体类型。比如执行let result = 5.squared(),编译器只能知道result是某个遵循Numeric的类型,但无法确定它是Int,后续你想把result当作Int使用(比如和其他Int做运算、调用Int的专属方法)都会报错,因为原类型信息已经丢失。而用Self作为返回类型时,编译器能明确知道返回的就是调用者的原类型,Int调用返回Int,Double调用返回Double,类型完全匹配。
3. 两种写法的核心区别
用Self作为返回类型
- 严格保证返回类型与调用者的具体类型完全一致,完整保留类型信息
- 贴合Numeric协议中乘法运算的原生行为(
*运算符本身就返回Self类型),逻辑自洽 - 调用后可以直接使用原类型的所有方法和属性,不需要额外的类型转换
用some Numeric作为返回类型
- 属于不透明返回类型,仅能表示返回一个遵循Numeric的类型,但无法确定具体是哪一种
- 会丢失原类型的具体信息,导致后续无法直接使用原类型的专属特性
- 不符合平方运算的设计意图(平方结果必然和原数同类型),且实际无法通过编译
内容的提问来源于stack exchange,提问作者wwuhoo
相关产品推荐
相关产品推荐

