在Swift中扩展通用整数类型

时间:2021-11-28 21:23:33

So I'm trying to extend Swift's integer types with a few convenient functions that I use a lot, however I'm not clear on which protocols I should be extending.

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

As an example, let's say I want to implement a function for clamping a value (if it's less than a minimum set it to that, otherwise if it's greater than a maximum then set it to that instead). My first thought was to do something like this:

举个例子,假设我想实现一个函数来绑定一个值(如果它小于最小值,那么将它设置为该值,否则如果它大于最大值,那么将它设置为该值)。我的第一个想法是做这样的事情:

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

Bit of a simplistic example, but it illustrates the problem; if I want to now call this for a UInt then naturally I can't, so I have to add an equivalent to UInt, but that won't work for a UInt16 and so-on.

有点简单的例子,但它说明了问题;如果我现在想调用UInt,那么我当然不能,所以我必须添加一个等价的UInt,但这对UInt16和某某都不行。

I thought that I could perhaps extend something higher up the chain, and use generics instead, however protocols such as IntegerType can't seem to be extended.

我认为我可以在链的上游扩展一些东西,然后使用泛型来代替,但是像IntegerType这样的协议似乎不能被扩展。

So, is there somewhere more appropriate that I could put my extension(s)?

那么,是否有更合适的地方放置我的扩展名?

5 个解决方案

#1


7  

For Swift 2, see Andriy Gordiychuk's answer, which will be correct then. If you require Swift 1, then this cannot be done with extensions, and must be done with free functions. This is why there are so many free functions in stdlib that became extensions in Swift 2.

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

For Swift 1, what you have to do is:

对于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
}

If you prefer modifying the value (as Andriy's example does), you can do it this way:

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

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

Otherwise you have to write an extension on every type. It's the only other answer in Swift 1. Swift 2 is much better.

否则,您必须为每个类型编写一个扩展。这是Swift 1中唯一的另一个答案。斯威夫特2要好多了。

#2


4  

While Swift 2.0 is still in beta I suggest you to add extensions like you illustrated. You will have to copy-paste the same code for Int, Int64 etc, but there is no other way to do what you want at the moment.

虽然Swift 2.0还在beta测试中,但我建议您添加扩展,如您所示。您将不得不为Int、Int64等复制粘贴相同的代码,但是目前没有其他方法可以做您想做的事情。

Once Swift 2.0 is out you will be able to do this

一旦Swift 2.0推出,你就能做到这一点。

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

If you can wait with the release of your app until some time in September then I encourage you to start using Swift 2.0 right now.

如果你可以等到9月份的某个时候再发布你的应用,我建议你现在就开始使用Swift 2.0。

Update

With Swift 2.0 you can also add extension to Comparable protocol which will ensure that clamp() is available for other types such as Double, Float, etc

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

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

#3


2  

By way of example, here is an integer implementation of clamped that also applies generically to anything that can use it:

举个例子,这里有一个整数实现,它也适用于任何可以使用它的东西:

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)
    }
}

And the test cases:

测试用例:

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

#4


1  

You are on the right track. Infact you are talking about Protocol Oriented Programming.

你在正确的轨道上。事实上,你说的是面向协议的编程。

Protocol extensions: Swift is very focused on protocol-oriented development — there’s even a session on the topic at WWDC 2015. Swift 2.0 adds protocol extensions, and the standard library itself uses them extensively. Where you used to use global functions, Swift 2.0 now adds methods to common types so functions chain naturally, and your code is much more readable.

协议扩展:Swift非常关注面向协议的开发——在WWDC 2015年甚至有一个关于这个主题的会议。Swift 2.0增加了协议扩展,标准库本身也广泛地使用它们。在以前使用全局函数的地方,Swift 2.0现在向通用类型添加了方法,这样函数就可以自然地进行链化,您的代码就更容易读懂了。

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

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

Infact a big feature of Swift 2.0 is that it allows you to add methods to protocols so you can add clamp to IntegerType.

实际上,Swift 2.0的一个重要特性是,它允许向协议添加方法,以便向IntegerType添加clamp。

The video explains very well the topic of Protocol Oriented Programming: https://developer.apple.com/videos/wwdc/2015/?id=408

视频很好地解释了面向协议编程的主题:https://developer.apple.com/videos/wwdc/2015/?id=408

You just need to upgrade to Swift 2.0.

你只需要升级到Swift 2.0。

#5


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
    }
}

#1


7  

For Swift 2, see Andriy Gordiychuk's answer, which will be correct then. If you require Swift 1, then this cannot be done with extensions, and must be done with free functions. This is why there are so many free functions in stdlib that became extensions in Swift 2.

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

For Swift 1, what you have to do is:

对于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
}

If you prefer modifying the value (as Andriy's example does), you can do it this way:

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

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

Otherwise you have to write an extension on every type. It's the only other answer in Swift 1. Swift 2 is much better.

否则,您必须为每个类型编写一个扩展。这是Swift 1中唯一的另一个答案。斯威夫特2要好多了。

#2


4  

While Swift 2.0 is still in beta I suggest you to add extensions like you illustrated. You will have to copy-paste the same code for Int, Int64 etc, but there is no other way to do what you want at the moment.

虽然Swift 2.0还在beta测试中,但我建议您添加扩展,如您所示。您将不得不为Int、Int64等复制粘贴相同的代码,但是目前没有其他方法可以做您想做的事情。

Once Swift 2.0 is out you will be able to do this

一旦Swift 2.0推出,你就能做到这一点。

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

If you can wait with the release of your app until some time in September then I encourage you to start using Swift 2.0 right now.

如果你可以等到9月份的某个时候再发布你的应用,我建议你现在就开始使用Swift 2.0。

Update

With Swift 2.0 you can also add extension to Comparable protocol which will ensure that clamp() is available for other types such as Double, Float, etc

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

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

#3


2  

By way of example, here is an integer implementation of clamped that also applies generically to anything that can use it:

举个例子,这里有一个整数实现,它也适用于任何可以使用它的东西:

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)
    }
}

And the test cases:

测试用例:

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

#4


1  

You are on the right track. Infact you are talking about Protocol Oriented Programming.

你在正确的轨道上。事实上,你说的是面向协议的编程。

Protocol extensions: Swift is very focused on protocol-oriented development — there’s even a session on the topic at WWDC 2015. Swift 2.0 adds protocol extensions, and the standard library itself uses them extensively. Where you used to use global functions, Swift 2.0 now adds methods to common types so functions chain naturally, and your code is much more readable.

协议扩展:Swift非常关注面向协议的开发——在WWDC 2015年甚至有一个关于这个主题的会议。Swift 2.0增加了协议扩展,标准库本身也广泛地使用它们。在以前使用全局函数的地方,Swift 2.0现在向通用类型添加了方法,这样函数就可以自然地进行链化,您的代码就更容易读懂了。

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

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

Infact a big feature of Swift 2.0 is that it allows you to add methods to protocols so you can add clamp to IntegerType.

实际上,Swift 2.0的一个重要特性是,它允许向协议添加方法,以便向IntegerType添加clamp。

The video explains very well the topic of Protocol Oriented Programming: https://developer.apple.com/videos/wwdc/2015/?id=408

视频很好地解释了面向协议编程的主题:https://developer.apple.com/videos/wwdc/2015/?id=408

You just need to upgrade to Swift 2.0.

你只需要升级到Swift 2.0。

#5


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
    }
}