Swift有一些文字,可用于初始化不同类型而无需显式调用其初始化程序。例如,
let x = 5 // x is now an Int
自动将x
推断为Int
类型。但是如果我们将变量的类型指定为其他东西
let x: UInt = 5 // x is now a UInt
编译器自动理解5
现在是无符号整数,因此必须调用相应的UInt
初始值设定项而不是Int
初始值设定项。
ExpressibleByIntegerLiteral
协议这适用于实现协议ExpressibleByIntegerLiteral
的所有类型。现在我将此协议一致性添加到我自己的类型中:
/// Represents a range of characters in a `String`.
//
/// The only purpose of this type is to provide a wrapper around `CountableClosedRange`
/// that can be initialized both with a range and an **integer literal**.
struct TextRange: ExpressibleByIntegerLiteral {
let range: CountableClosedRange<Int>
var lowerBound: Int {
return range.lowerBound
}
var upperBound: Int {
return range.upperBound
}
init(_ range: CountableClosedRange<Int>) {
self.range = range
}
// This initializer adds the protocol conformance:
init(integerLiteral value: Int) {
self.range = value...value
}
}
根据这个定义,我可以写:
let x: TextRange = 5 // x is now a `TextRange`
然而,
let x = 5 // x is now an `Int`
仍然推断x为Int
。到目前为止,非常好。
...
运算符现在,我还希望能够使用这样的封闭范围运算符TextRange
创建...
:
let y: TextRange = 5...10
所以我在...
s的扩展名中重载TextRange
运算符:
extension TextRange {
/// Given two text ranges, this operator creates a new text range that incorporates
/// the integers within the operand ranges as well as all integers between the operand ranges.
///
/// - Parameters:
/// - lowerRange: A text range whose lower bound is smaller than the lower bound of `upperRange`.
/// - upperRange: A text range whose lower bound is greater than the lower bound of `lowerRange`.
/// - Returns: A `TextRange` from the first operand's lower bound to the second operand's upper bound.
static func ...(lowerRange: TextRange, upperRange: TextRange) -> TextRange {
let lowerBound = lowerRange.lowerBound
let upperBound = max(lowerRange.upperBound, upperRange.upperBound)
assert(lowerBound <= upperBound, "Cannot create a TextRange because lowerBound > upperBound.")
return TextRange(lowerBound...upperBound)
}
}
这就是我遇到麻烦的地方。 (多么令人惊讶:麻烦始于运算符重载! )
对于TextRange
类型的变量,此运算符按预期工作,但当我省略类型注释时,变量仍然实例化为TextRange
:
let y = 5...10 // y is now a `TextRange`
那不应该因为:
如果没有为变量指定类型,
整数文字的默认推断类型是Swift标准库类型Int。
(见Integer Literals in The Swift Programming Language)
因此,我希望将5
和10
推断为Int
,而不是TextRange
。
...
运算符的重载仅针对TextRange
类型的两个操作数实现。因此,如果x...y
和...
都是x
s,y
仍应使用Int
的原始Swift实现。
那么为什么编译器会决定&#34;它现在应该默认使用重载运算符作为两个整数文字之间的范围,并将模式x
中的y
和x...y
解释为TextRange
s?