Swift4中Collection扩展mutating函数报错:'self'不可变,原因何在?
问题原因及解决方案
这个报错的核心原因其实是**Collection 协议本身是为只读集合场景设计的**,它并没有提供修改集合结构或元素的契约支持。
你可能以为加了 mutating 关键字就能让 self 可变,但实际上 mutating 只是告诉编译器「这个方法会修改实例本身」,但前提是当前协议/类型本身允许 self 被修改——而 Collection 并不做这个保证:所有实现 Collection 的类型,既可能是可变的(比如 Array),也可能是不可变的(比如某些自定义只读集合,或者被声明为 let 的值类型集合实例)。编译器不可能为了你的方法打破 Collection 协议的只读约定,所以才会抛出这个错误。
另外还要注意:你调用的 removeFirst() 方法本身就不属于 Collection 协议的范畴,它是 RangeReplaceableCollection 协议提供的——这个协议专门负责支持集合的增删操作(也就是修改集合长度的能力)。
所以正确的做法是,把你的扩展放到 RangeReplaceableCollection 上,而不是 Collection:
extension RangeReplaceableCollection { mutating func f() { removeFirst() } }
这样做的原因是:
RangeReplaceableCollection继承自MutableCollection,本身就保证了实例是可以被修改的;- 它自带了
removeFirst()、append()等修改集合结构的方法,编译器不会再报错。
如果只是需要修改集合元素(而非增删元素),扩展 MutableCollection 就足够,但因为你用到了 removeFirst(),所以必须基于 RangeReplaceableCollection 来扩展。
内容的提问来源于stack exchange,提问作者HORI Taisuke
相关产品推荐
相关产品推荐

