Swift扩展Array自定义下标为何不用index参数名会触发subscript歧义报错
自定义Array扩展下标触发「Ambiguous use of 'subscript(_:)'」的根本原因
这个报错和内部参数名是不是index完全无关,核心是你定义的下标调用签名和Array原生下标撞了,编译器没法判断你到底要调哪个方法。
先讲Swift下标的默认参数规则
Swift对下标的参数标签有默认处理逻辑:
- 如果你不给下标参数显式写外部参数名,编译器会默认给所有下标参数加
_作为外部标签,意思是调用的时候不用写参数名,直接传值就行。 - Array自带的普通下标原生签名就是
subscript(_ index: Int) -> Element,对应我们平时写的arr[0]这种写法,不需要加任何参数标签。
两段代码的本质差异
能正常运行的版本
subscript(i index: Int) -> (String, String)?
这里你显式给参数指定了外部标签i,index只是内部用的参数名。这个自定义下标的调用形式必须写成arr[i: 0],和原生的arr[0]写法完全不一样,编译器一眼就能区分开两个方法,根本不会有歧义,自然能正常跑。
报错的版本
subscript(i: Int) -> (String, String)?
这里你没显式指定外部参数标签,编译器就按默认规则给参数加了_当外部标签,最后这个下标的调用签名变成了subscript(_: Int) -> (String, String)?,和原生的subscript(_: Int) -> Element调用形式完全一致:都是传一个Int,不用写参数标签。
这时候你写let val = arr[0],编译器根本猜不到你是想拿数组本身的元素,还是想拿你自定义的(String, String)?类型返回值,直接报歧义错误。
常见误区
别被第一段代码里的index参数名误导了,内部参数名对调用签名没有任何影响:
- 你就算把正常版本的内部参数名改成
abc,只要外部标签还是非_的值,比如写成subscript(i abc: Int),一样能正常运行。 - 反过来就算你内部参数名用
index,只要外部标签显式写成_,比如subscript(_ index: Int) -> (String,String)?,一样会报一模一样的歧义错误。
内容的提问来源于stack exchange,提问作者byaruhaf
相关产品推荐
相关产品推荐

