为什么使用索引以外的参数名称会导致 'subscript(_:)' 的使用不明确
Why does using a parameter name other the index result in Ambiguous use of 'subscript(_:)'
采用下面的两个片段,上面的片段工作正常但下面的结果
'subscript(_:)'
的使用不明确
使用索引 ✅
extension Array {
subscript(i index: Int) -> (String, String)? {
guard let value = self[index] as? Int else {
return nil
}
switch (value >= 0, abs(value % 2)) {
case (true, 0): return ("positive", "even")
case(true, 1): return ("positive", "odd")
case(false, 0): return ("negative", "even")
case(false, 1): return ("negative", "odd")
default: return nil
}
}
}
不使用索引 ❌
extension Array {
subscript(i: Int) -> (String, String)? {
guard let value = self[i] as? Int else {
return nil
}
switch (value >= 0, abs(value % 2)) {
case (true, 0): return ("positive", "even")
case(true, 1): return ("positive", "odd")
case(false, 0): return ("negative", "even")
case(false, 1): return ("negative", "odd")
default: return nil
}
}
}
首先,名称index
与问题无关;可以是任何名字。
实际问题是Array
already has a subscript that takes an unlabeled Int
.
您的第一个重载没有相同的输入签名。相反,它需要一个参数标签:
[1][i: 0] // ("positive", "odd")
你可以仍然使用没有标签的重载…
extension Array where Element: BinaryInteger {
subscript(: Int) -> (String, String) {
let value: Element = self[]
return (
value >= 0 ? "positive" : "negative",
value.isMultiple(of: 2) ? "even" : "odd"
)
}
}
...但是,正如下标主体本身所必需的那样,您需要始终显式键入结果,以便从标准库访问重载,因为您自己的模块中的任何内容都将优先考虑。
[1][0] // ("positive", "odd")
[1][0] as Int // 1
因此,我建议使用带标签的下标或方法。*
* 我想推荐的是命名下标。但是 Swift 没有。但是,您可以使用更多类型来模拟它们。像这样:
extension Array where Element: BinaryInteger {
struct InfoStrings {
fileprivate let array: Array
}
var infoStrings: InfoStrings { .init(array: self) }
}
extension Array.InfoStrings {
subscript(index: Int) -> (String, String) {
let value = array[index]
return (
value >= 0 ? "positive" : "negative",
value.isMultiple(of: 2) ? "even" : "odd"
)
}
}
[1].infoStrings[0]
采用下面的两个片段,上面的片段工作正常但下面的结果 'subscript(_:)'
的使用不明确使用索引 ✅
extension Array {
subscript(i index: Int) -> (String, String)? {
guard let value = self[index] as? Int else {
return nil
}
switch (value >= 0, abs(value % 2)) {
case (true, 0): return ("positive", "even")
case(true, 1): return ("positive", "odd")
case(false, 0): return ("negative", "even")
case(false, 1): return ("negative", "odd")
default: return nil
}
}
}
不使用索引 ❌
extension Array {
subscript(i: Int) -> (String, String)? {
guard let value = self[i] as? Int else {
return nil
}
switch (value >= 0, abs(value % 2)) {
case (true, 0): return ("positive", "even")
case(true, 1): return ("positive", "odd")
case(false, 0): return ("negative", "even")
case(false, 1): return ("negative", "odd")
default: return nil
}
}
}
首先,名称index
与问题无关;可以是任何名字。
实际问题是Array
already has a subscript that takes an unlabeled Int
.
您的第一个重载没有相同的输入签名。相反,它需要一个参数标签:
[1][i: 0] // ("positive", "odd")
你可以仍然使用没有标签的重载…
extension Array where Element: BinaryInteger {
subscript(: Int) -> (String, String) {
let value: Element = self[]
return (
value >= 0 ? "positive" : "negative",
value.isMultiple(of: 2) ? "even" : "odd"
)
}
}
...但是,正如下标主体本身所必需的那样,您需要始终显式键入结果,以便从标准库访问重载,因为您自己的模块中的任何内容都将优先考虑。
[1][0] // ("positive", "odd")
[1][0] as Int // 1
因此,我建议使用带标签的下标或方法。*
* 我想推荐的是命名下标。但是 Swift 没有。但是,您可以使用更多类型来模拟它们。像这样:
extension Array where Element: BinaryInteger {
struct InfoStrings {
fileprivate let array: Array
}
var infoStrings: InfoStrings { .init(array: self) }
}
extension Array.InfoStrings {
subscript(index: Int) -> (String, String) {
let value = array[index]
return (
value >= 0 ? "positive" : "negative",
value.isMultiple(of: 2) ? "even" : "odd"
)
}
}
[1].infoStrings[0]