Post

🧀 通过deref间接调用方法

昨天看 RefCell<T> 文档的时候,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#[derive(Debug)]
enum List {
    Cons(Rc<RefCell<i32>>, Rc<List>),
    Nil,
}

use crate::List::{Cons, Nil};
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let value = Rc::new(RefCell::new(5));

    let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));

    let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));
    let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a));

    *value.borrow_mut() += 10;

    println!("a after = {:?}", a);
    println!("b after = {:?}", b);
    println!("c after = {:?}", c);
}

对于 *value.borrow_mut() += 10 的解释

After we’ve created the lists in a, b, and c, we want to add 10 to the value in value. We do this by calling borrow_mut on value, which uses the automatic dereferencing feature we discussed in Chapter 5 (see the section “Where’s the -> Operator?”) to dereference the Rc to the inner RefCell value. The borrow_mut method returns a RefMut smart pointer, and we use the dereference operator on it and change the inner value.

这里让我不仅好奇,是不是这样的?

就是

1
x -- Deref --> y

类型x可以通过Deref得到类型y

假如 y 有一个方法 fn foo(&self)

那是不是 x可以直接调用这个foo,也就是 x.foo() 行得通?

结论是可以的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
struct Tess{
    val: String,
    id: i32,
}

use std::ops::Deref;

impl Deref for Tess{
    type Target = String;

    fn deref(&self) -> &Self::Target{
        &self.val
    }
}

fn main(){
    let a = Tess{val:"hello".to_string(),id:3};
    println!("{}",*a);
    println!("{}",a.len()); //直接调用String的方法len
}

/*
hello
5
*/

至于为什么,上面也提到了,主要涉及到两点,我认为

  1. when you call a method with object.something(), Rust automatically adds in &, &mut, or * so object matches the signature of the method
  2. Deref Coercion

因为1, a.len()实际上是(&a).len() 因为2, &a&Tess, 而fn len(&self)这里其实是需要 &String ,然后通过 Deref Coercion 得到&String ,从而完成调用。

This post is licensed under CC BY 4.0 by the author.