Swift中为什么无法在init()调用后链式调用mutating方法?
报错核心原因
Foo()生成的是值类型的临时右值实例,默认是不可变的。你定义的add(_:)是mutating方法,这类方法要求调用它的实例必须是被var修饰的可修改左值,临时实例不满足该要求,因此编译器直接抛出错误。
不符合预期的本质原因
你理解的执行流程默认把临时实例当成了可变对象处理,但Swift的值类型语义有明确规定:
- 没有被赋值给
var变量的临时值类型实例,默认是只读的,不允许任何修改操作 mutating方法的本质是:方法执行时会将调用它的实例的整个内存空间标记为可修改,修改完成后生成新的实例替换原实例,这个操作只能作用在可写的左值上,不能作用在临时只读的右值上
各测试用例表现差异的原因
- 测试用例1中你先把
Foo()赋值给了var修饰的test1变量,此时test1是可修改的左值,自然可以调用mutating方法,也支持后续的赋值操作,所以执行正常 - 测试用例2、3的操作都只是读取或直接丢弃临时实例、没有修改需求,不会触发
mutating方法的可变校验,因此执行正常
修复方案
如果想要支持链式调用的写法,只需要把add(_:)改为非mutating方法,内部生成新实例返回即可:
struct Foo { var x: Int = 0 // 去掉mutating修饰,内部生成新实例修改后返回 func add(_ y: Int) -> Foo { var newInstance = self newInstance.x += y return newInstance } } // 此时该写法不会再报错 var success = Foo().add(42)
内容的提问来源于stack exchange,提问作者user14873944
相关产品推荐
相关产品推荐

