9

所以我试图用一些我经常使用的方便的函数来扩展 Swift 的整数类型,但是我不清楚我应该扩展哪些协议。

例如,假设我想实现一个用于钳位值的函数(如果它小于最小值,则将其设置为该值,否则如果它大于最大值,则将其设置为该值)。我的第一个想法是做这样的事情:

extension Int {
    func clamp(minimum:Int, maximum:Int) {
        if self < minimum { return minimum }
        if self > maximum { return maximum }
        return self
    }
}

有点简单的例子,但它说明了问题;如果我现在想把它称为 aUInt那么我自然不能,所以我必须添加一个等价于UInt,但这不适用于 aUInt16等等。

我认为我也许可以在链上扩展一些东西,并改用泛型,但是IntegerType似乎无法扩展诸如此类的协议。

那么,有没有更合适的地方可以放置我的扩展名?

4

5 回答 5

8

对于 Swift 2,请参阅 Andriy Gordiychuk 的答案,这将是正确的。如果您需要 Swift 1,那么这不能通过扩展来完成,而必须通过自由函数来完成。这就是为什么 stdlib 中有这么多免费函数在 Swift 2 中成为扩展的原因。

对于 Swift 1,你要做的是:

func clamp<T:Comparable>(value: T, #minimum:T, #maximum:T) -> T {
    if value < minimum { return minimum }
    if value > maximum { return maximum }
    return value
}

如果您更喜欢修改值(如 Andriy 的示例所做的那样),您可以这样做:

func clamp<T:Comparable>(inout value: T, #minimum:T, #maximum:T) {
    if value < minimum { value = minimum }
    else if value > maximum { value = maximum }
}

否则,您必须为每种类型编写扩展。这是 Swift 1 中唯一的其他答案。Swift 2 要好得多。

于 2015-08-11T15:09:14.787 回答
4

虽然 Swift 2.0 仍处于测试阶段,但我建议您添加如图所示的扩展。您将不得不复制粘贴相同的代码IntInt64,但目前没有其他方法可以做您想做的事情。

Swift 2.0 发布后,您将能够做到这一点

extension IntegerType {
    mutating func clamp(minimum:Self, maximum:Self) {
        if self < minimum { self = minimum }
        if self > maximum { self = maximum }
    }
}

如果您可以等到 9 月的某个时间发布您的应用程序,那么我鼓励您现在就开始使用 Swift 2.0。

更新

使用 Swift 2.0,您还可以向Comparable协议添加扩展,这将确保clamp()可用于其他类型,例如Double,Float

extension Comparable {
    mutating func clamp(minimum:Self, maximum:Self) {
        if self < minimum { self = minimum }
        if self > maximum { self = maximum }
    }
}
于 2015-08-11T15:03:14.973 回答
2

举例来说,这是一个整数实现,clamped它也普遍适用于任何可以使用它的东西:

extension Comparable
{
    func clamped(from lowerBound: Self, to upperBound: Self) -> Self {
        return min(max(self, lowerBound), upperBound)
    }

    func clamped(to range: ClosedRange<Self>) -> Self {
        return min(max(self, range.lowerBound), range.upperBound)
    }
}

extension Strideable where Self.Stride: SignedInteger
{
    func clamped(to range: CountableClosedRange<Self>) -> Self {
        return min(max(self, range.lowerBound), range.upperBound)
    }
}

和测试用例:

7.clamped(from: 3, to: 6)   // 6

7.clamped(to: 3 ... 6)      // 6
7.clamped(to: 3 ... 7)      // 7
7.clamped(to: 3 ... 8)      // 7

7.0.clamped(to: 3.0 ... 6.0)  // 6
7.0.clamped(to: 3.0 ... 7.0)  // 7
7.0.clamped(to: 3.0 ... 8.0)  // 7
于 2017-05-03T20:51:41.677 回答
1

你在正确的轨道上。实际上,您正在谈论面向协议的编程。

协议扩展: Swift 非常专注于面向协议的开发——在 WWDC 2015 上甚至有一个关于该主题的会议。Swift 2.0 添加了协议扩展,标准库本身广泛使用它们。在您过去使用全局函数的地方,Swift 2.0 现在向常用类型添加了方法,因此函数链自然而然,并且您的代码更具可读性。

https://developer.apple.com/swift/blog/?id=29

事实上 Swift 2.0 的一大特点是它允许你向协议中添加方法,这样你就可以添加clampIntegerType.

该视频很好地解释了以下主题Protocol Oriented Programminghttps ://developer.apple.com/videos/wwdc/2015/?id=408

你只需要升级到 Swift 2.0。

于 2015-08-11T14:15:32.987 回答
1
extension Comparable {
    func clamp(var minimum: Self, var _ maximum: Self) -> Self {
        if maximum < minimum { swap(&maximum, &minimum) }
        if self < minimum { return minimum }
        if self > maximum { return maximum }
        return self
    }
}
于 2015-11-08T09:25:45.153 回答