Deret
首先先看一段代码
fn main() {
let x = 5;
let y = &x;
assert_eq!(5, x);
assert_eq!(5, y)
}
编译的时候报错:
error[E0277]: can't compare `{integer}` with `&{integer}`
--> src/main.rs:6:5
|
6 | assert_eq!(5, y)
| ^^^^^^^^^^^^^^^^ no implementation for `{integer} == &{integer}`
|
= help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
具体原因是因为不能拿一个数值和一个引用做比较,可以像下面这样写不报错
fn main() {
let x = 5;
let y = &x;
assert_eq!(5, x);
assert_eq!(5, *y)
}
也可以这样写
fn main() {
let x = 5;
let y = Box::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
其实,在RUST中,使用*就是调用对应结构体的deref()方法,所以我们也可以自己实现一个Box像下面这样:
use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
fn main() {
let x = 5;
let y = MyBox::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
强制隐式转换
use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
fn hello(name: &str) {
println!("Hello, {}!", name);
}
fn main() {
let m = MyBox::new(String::from("Rust"));
hello(&m);
}
- 注意hello的参数是&str
- 我们传入的参数是&MyBox<String>类型
- MyBox实现了Deref trait,Rust就可以通过调用MyBox的deref把&MyBox转变成&String
- 由于标准库对String又有一个Deref的实现将string转换为string slice,所以这里又把&String转换&str