Swift中元素类型为Comparable的范围类型为何不遵循Comparable协议?
这个问题问得挺戳中痛点的——我刚用Swift范围类型的时候也纳闷:既然范围里的元素都是Comparable的,为啥不能直接用<、<=这些运算符比较整个范围呢?咱们慢慢理清楚:
先澄清:不是所有范围类型都不遵循Comparable
你提到的PartialRangeFrom(比如5...)、PartialRangeUpTo(比如..<10)、PartialRangeThrough(比如...10)这类单侧范围其实是遵循Comparable协议的。为啥?因为它们的比较逻辑太明确了:
- 比如
a... < b...,本质就是比较起始值a和b; ..<x <= ..<y就是比较上限x和y;
完全没有歧义,所以标准库直接给它们实现了Comparable。
那为啥闭区间(ClosedRange,比如1...10)不行?
核心原因是:两个闭区间的“大小”没有统一的、无歧义的定义。你想啊,如果要比较1...10和2...9,应该按什么规则来?
- 比起始值:
1 < 2,那1...10更小? - 比结束值:
10 > 9,那1...10更大? - 比区间长度:两者都是9个元素,应该相等?
- 比包含关系:谁也不包含谁,那怎么算大小?
不同场景下开发者的需求天差地别,Swift标准库不会替你做这个选择——要是随便选一种逻辑实现,反而会误导很多开发者,引发意料之外的bug。所以干脆不给ClosedRange实现Comparable,把自定义比较的权力交给你。
那为啥==可以用?
因为相等的定义是绝对明确的:两个闭区间相等,当且仅当它们的起始值和结束值完全一致(也就是rangeFive.lowerBound == rangeSix.lowerBound && rangeFive.upperBound == rangeSix.upperBound)。这个逻辑没争议,所以标准库给所有范围类型都实现了Equatable协议(==是Equatable的核心要求),但没延伸到Comparable。
关于你代码里的报错
你写的minRangeFive < maxRangeSix报错,是因为min()和max()返回的是可选类型(比如Int?)——如果是空区间的话,这两个方法会返回nil。Swift不允许直接比较两个可选值,你得先安全解包:
let rangeFive = 1...10 let rangeSix = 1...10 if let minFive = rangeFive.min(), let maxSix = rangeSix.max() { print(minFive < maxSix) // 这里就能正常运行了 }
备注:内容来源于stack exchange,提问作者Michael

