Rust trait实现中self用法疑问:Vec调用push/append方法报错问题
报错核心原因
报错的本质是两个基础规则不匹配:
- 你定义的
AppendBartrait要求append_bar方法返回Self类型 Vec的push、append方法都是原地修改集合,返回值为单元类型(),和要求的返回值不匹配;而String的加法运算符是返回新的String实例,刚好符合返回值要求,所以String的实现可以正常运行。
各个错误实现的具体问题
第一个Vec实现问题
impl AppendBar for Vec<String> { fn append_bar(self) -> Self{ let mut bar = vec![String::from("Bar")]; bar.push(self); bar } }
- 类型不匹配错误:
Vec<String>的push方法接收的参数是单个String元素,你传入了整个Vec<String>类型的self,完全不符合参数类型要求。 - 逻辑错误:该实现是把原有vec的内容加到"Bar"后面,和预期把"Bar"追加到原有vec后的逻辑相反。
第二个Vec实现问题
impl AppendBar for Vec<String> { fn append_bar(self) -> Self{ let bar_vec = vec!["Bar".to_string()]; self.append(bar_vec) } }
- 可变性错误:参数
self没有加mut修饰,不可变的实例不能调用append这种原地修改的方法。 - 返回值类型错误:
append方法原地把参数里的元素追加到调用者集合后,返回值是(),和要求返回的Vec<String>类型不匹配。 - 该实现的修正版本如下:
impl AppendBar for Vec<String> { // 给self加mut修饰,允许原地修改 fn append_bar(mut self) -> Self{ let mut bar_vec = vec!["Bar".to_string()]; // append要求参数是可变引用,调用后self已经被修改 self.append(&mut bar_vec); // 手动返回修改后的self self } }
第三个Vec实现问题
trait AppendBar<T> { fn append_bar(self) -> Self; } impl<T> AppendBar<T> for Vec<T> { fn append_bar(self) -> Self{ self.push("Bar".to_string()) } }
- 可变性错误:同第二个实现,
self没有mut修饰,不可变实例不能调用push。 - 返回值类型错误:
push返回(),不符合返回Self的要求。 - 泛型约束错误:你给所有泛型
Vec<T>实现这个trait,但代码里硬写了String类型的"Bar"值,只要T不是String就会触发类型不匹配,泛型逻辑完全不成立。
trait实现中self的使用规则
fn func(self):方法会获取调用者的所有权,调用后原变量无法再使用,可以在方法签名中给self加mut修饰来修改实例,最后可返回修改后的实例。fn func(&self):方法只获取调用者的不可变引用,只能读取不能修改,适合纯读取的方法。fn func(&mut self):方法获取调用者的可变引用,可以原地修改调用者,不需要转移所有权,也不需要返回原实例。- 标准库所有集合类型的原地修改方法(比如Vec的push、append,String的push_str等)默认都使用
&mut self作为参数,返回(),如果你的方法要求返回Self,需要手动把修改后的实例返回。 - String的
+运算符本质是调用add方法,会获取左值的所有权,修改后返回新的String实例,所以刚好符合你定义的trait的返回要求。
内容的提问来源于stack exchange,提问作者my_stack
相关产品推荐
相关产品推荐

