编写自定义扩展时的代码重复性

时间:2020-10-19 08:19:13

标签: swift

我经常遇到这样的情况:

 public extension CountableRange {
     func advanced(by n: Bound.Stride) -> Self {
        let lowerBound = self.lowerBound.advanced(by: n)
        let upperBound = self.upperBound.advanced(by: n)
        return .init(uncheckedBounds: (lowerBound, upperBound))
    }
    
    static func + (lhs: Self, rhs: Bound.Stride) -> Self {
        lhs.advanced(by: rhs)
    }
    
    static func - (lhs: Self, rhs: Bound.Stride) -> Self {
        lhs.advanced(by: -rhs)
    }
}

//--------------------------------------------------------

public extension CountableClosedRange {
    func advanced(by n: Bound.Stride) -> Self {
        let lowerBound = self.lowerBound.advanced(by: n)
        let upperBound = self.upperBound.advanced(by: n)
        return .init(uncheckedBounds: (lowerBound, upperBound))
    }
    
    static func + (lhs: Self, rhs: Bound.Stride) -> Self {
        lhs.advanced(by: rhs)
    }
    
    static func - (lhs: Self, rhs: Bound.Stride) -> Self {
        lhs.advanced(by: -rhs)
    }
}

完全相同的两段代码。有什么办法可以解决吗?
如果CountableRangeCountableClosedRange符合某个通用协议BasicRange,我可以为该BasicRange协议编写一个扩展名。但通常并非如此。

1 个答案:

答案 0 :(得分:4)

您可以使用协议默认实现将功能添加到几种内置类型。

您只需要声明一个协议,并使用所需功能的默认实现对其进行扩展,然后使想要具有此功能的内置类型符合该协议,它们将免费获得默认实现。 / p>

public protocol BasicRange: RangeExpression where Bound: Strideable {
    var lowerBound: Bound { get }
    var upperBound: Bound { get }
    init(uncheckedBounds bounds: (lower: Bound, upper: Bound))
    func advanced(by n: Bound.Stride) -> Self
    static func + (lhs: Self, rhs: Bound.Stride) -> Self
    static func - (lhs: Self, rhs: Bound.Stride) -> Self
}

public extension BasicRange {
    func advanced(by n: Bound.Stride) -> Self {
        let lowerBound = self.lowerBound.advanced(by: n)
        let upperBound = self.upperBound.advanced(by: n)
        return .init(uncheckedBounds: (lowerBound, upperBound))
    }

    static func + (lhs: Self, rhs: Bound.Stride) -> Self {
        lhs.advanced(by: rhs)
    }

    static func - (lhs: Self, rhs: Bound.Stride) -> Self {
        lhs.advanced(by: -rhs)
    }
}

extension CountableRange: BasicRange {}
extension CountableClosedRange: BasicRange {}

CountableRange(uncheckedBounds: (1,5)).advanced(by: 1)
CountableClosedRange(uncheckedBounds: (1,5)).advanced(by: 1)
相关问题