这里发生了什么(游乐场)?
struct Number {
num: i32
}
impl Number {
fn set(&mut self, new_num: i32) {
self.num = new_num;
}
fn get(&self) -> i32 {
self.num
}
}
fn main() {
let mut n = Number{ num: 0 };
n.set(n.get() + 1);
}
Run Code Online (Sandbox Code Playgroud)
给出了这个错误:
error[E0502]: cannot borrow `n` as immutable because it is also borrowed as mutable
--> <anon>:17:11
|
17 | n.set(n.get() + 1);
| - ^ - mutable borrow ends here
| | |
| | …Run Code Online (Sandbox Code Playgroud) 我们可以实现traits core::ops来定义我们类型的运算符的行为.特征本身用#[lang =...]属性注释,因此编译器知道哪些特征和操作符属于一起.
例如,Add基本类型的实现看起来像这样(宏从这里手动扩展和简化):
impl Add for i32 {
type Output = i32;
fn add(self, other: i32) -> i32 {
self + other
}
}
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,该实现在+内部使用运算符,可能会调用self.add(other),从而导致无限递归.显然,事情不会发生这种情况,因为像3 + 4(假设没有不断的折叠)这样的表达式可以完美地运行.
现在考虑这个特性的天真实现Add:
use std::ops::Add;
struct Foo;
impl Add for Foo {
type Output = Foo;
fn add(self, other: Foo) -> Foo {
self + other
}
}
fn main() {
let two_foo = Foo + Foo;
}
Run Code Online (Sandbox Code Playgroud)
编译器警告 …