想在Swift3中添加一些糖来玩具。基本上,我希望能够做到这样的事情:
let randomAdjust = (-10...10).random
为此,我决定扩展ClosedRange
。但后来发现它可能对我的情况更好,我真的只是计划现在做Int,使用CountableClosedRange
。我最近的多次尝试看起来像:
extension CountableClosedRange where Bound == Int {
var random:Int {
return Int(arc4random_uniform(UInt32(self.count) + 1)) + self.lowerBound
}
}
但游乐场抱怨道:
error: same-type requirement makes generic parameter 'Bound' non-generic
extension CountableClosedRange where Bound == Int {
我甚至不知道它在那里告诉我什么。
答案 0 :(得分:8)
通常遇到此障碍的方式是尝试扩展Array时。这是合法的:
extension Array where Element : Comparable {
}
但这是非法的:
extension Array where Element == Int {
}
编译器抱怨:
相同类型的要求使通用参数'Element'非通用
问题是这里使用==
和Array的参数化类型Element,因为Array是一个通用的 struct 。
使用Array的一个解决方法是提升Array继承的层次结构,以达到不是通用结构的东西:
extension Sequence where Iterator.Element == Int {
}
这是合法的,因为Sequence和Iterator是通用的协议。
另一种解决方案是从目标类型(即Int)提升层次结构。如果我们可以找到Int符合的协议,那么我们可以使用:
运算符而不是==
。嗯,有一个:
extension CountableClosedRange where Bound : Integer {
}
这是我们在范围内实施random
的两次尝试之间的真正区别。您尝试遇到包版广告的原因是mine没有使用==
,而我正在使用:
。我可以这样做,因为有一个Double符合的协议(FloatingPoint)。
但是,正如你所知,幸运的是,所有这些诡计很快就会成为过去。
答案 1 :(得分:0)
在Swift 4中,现在完全支持您的尝试。哇!
Swift文档中的示例:https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID553