Swift

时间:2017-08-15 09:29:56

标签: swift operator-overloading operators type-inference literals

字面

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

    因此,我希望将510推断为Int,而不是TextRange

  • ...运算符的重载仅针对TextRange类型的两个操作数实现。因此,如果x...y...都是x s,y仍应使用Int的原始Swift实现。

那么为什么编译器会决定&#34;它现在应该默认使用重载运算符作为两个整数文字之间的范围,并将模式x中的yx...y解释为TextRange s?

有没有办法告诉编译器默认情况下应该使用哪个运算符,以防未指定两个操作数的类型?

0 个答案:

没有答案