无法扩展特定类型的通用结构

Tra*_*ggs 0 swift3

想在Swift3中添加一些糖玩具.基本上,我希望能够做到这样的事情:

let randomAdjust = (-10...10).random
Run Code Online (Sandbox Code Playgroud)

为此,我决定扩展ClosedRange.但后来发现它对我的情况可能会更好,我真的只是计划在现在做Int,使用CountableClosedRange.我最近的多次尝试看起来像:

extension CountableClosedRange where Bound == Int {
    var random:Int {
        return Int(arc4random_uniform(UInt32(self.count) + 1)) + self.lowerBound
    }
}
Run Code Online (Sandbox Code Playgroud)

但游乐场抱怨说:

error: same-type requirement makes generic parameter 'Bound' non-generic
extension CountableClosedRange where Bound == Int {
Run Code Online (Sandbox Code Playgroud)

我甚至都不知道它在那里告诉我什么.

mat*_*att 8

通常遇到此障碍的方式是尝试扩展Array时.这是合法的:

extension Array where Element : Comparable {
}
Run Code Online (Sandbox Code Playgroud)

但这是非法的:

extension Array where Element == Int {
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨:

相同类型的要求使通用参数'Element'非通用

问题是==这里结合使用Array的参数化类型Element,因为Array是一个通用结构.

Array的一个解决方法是提升Array继承的层次结构,以达到不是通用结构的东西:

extension Sequence where Iterator.Element == Int {
}
Run Code Online (Sandbox Code Playgroud)

这是合法的,因为Sequence和Iterator是通用协议.

但是,另一种解决方案是从目标类型(即Int)提升层次结构.如果我们可以找到Int符合的协议,那么我们可以使用:运算符代替==.嗯,有一个:

extension CountableClosedRange where Bound : Integer {
}
Run Code Online (Sandbox Code Playgroud)

这是我们两次尝试random在范围上实现的真正区别.原因您尝试打一个路障和矿山并不为你使用==,而我使用:.我可以这样做,因为有一个Double符合的协议(FloatingPoint).

但是,正如你所知,幸运的是,所有这些诡计很快就会成为过去.

  • 并且`扩展数组,其中Element == Int`现在在Swift 3.1中是合法的,可与Xcode 8.3 beta一起使用:) (8认同)