Dmi*_*rov 8 smart-pointers rust trait-objects
我最初在这里问过这个问题,但它被标记为重复,尽管在我看来它只重复了其中的一部分,所以我创建了一个更具体的问题:
考虑以下代码:
use std::rc::Rc;
trait MyTrait {
fn trait_func(&self);
}
struct MyStruct1;
impl MyStruct1 {
fn my_fn(&self) {
// do something
}
}
impl MyTrait for MyStruct1 {
fn trait_func(&self) {
// do something
}
}
fn my_trait_fn(t: Rc<dyn MyTrait>) {
t.trait_func();
}
fn main() {
let my_str: Rc<MyStruct1> = Rc::new(MyStruct1);
my_trait_fn(my_str.clone());
my_str.my_fn();
}
Run Code Online (Sandbox Code Playgroud)
这段代码工作正常。现在我想更改 的定义trait_func以接受 a &mut self,但它不会像Rc仅适用于不可变数据那样工作。我使用的解决方案是包装MyTrait成RefCell:
use std::cell::RefCell;
fn my_trait_fn(t: Rc<RefCell<Box<dyn MyTrait>>>) {
t.borrow_mut().trait_func();
}
fn main() {
let my_str: Rc<RefCell<Box<MyStruct1>>> = Rc::new(RefCell::new(Box::new(MyStruct1)));
my_trait_fn(my_str.clone());
my_str.my_fn();
}
Run Code Online (Sandbox Code Playgroud)
当我编译它时,我收到一个错误:
use std::rc::Rc;
trait MyTrait {
fn trait_func(&self);
}
struct MyStruct1;
impl MyStruct1 {
fn my_fn(&self) {
// do something
}
}
impl MyTrait for MyStruct1 {
fn trait_func(&self) {
// do something
}
}
fn my_trait_fn(t: Rc<dyn MyTrait>) {
t.trait_func();
}
fn main() {
let my_str: Rc<MyStruct1> = Rc::new(MyStruct1);
my_trait_fn(my_str.clone());
my_str.my_fn();
}
Run Code Online (Sandbox Code Playgroud)
解决这个问题的最佳方法是什么?
(这个答案的较旧版本基本上建议克隆底层结构并将其放入一个新Rc<RefCell<Box<MyTrait>>对象中;这在稳定的 Rust 上当时是必要的,但因为在那之后不久,Rc<RefCell<MyStruct>>将强制执行而Rc<RefCell<MyTrait>>不会遇到麻烦。)
丢掉Box<>包装纸,你就可以自由轻松地施压Rc<RefCell<MyStruct>>了。Rc<RefCell<MyTrait>>回想一下,克隆 aRc<T>只是产生另一个Rc<T>,将引用计数增加一,您可以执行以下操作:
use std::rc::Rc;\nuse std::cell::RefCell;\n\ntrait MyTrait {\n fn trait_func(&self);\n}\n\n#[derive(Clone)]\nstruct MyStruct1;\nimpl MyStruct1 {\n fn my_fn(&self) {\n // do something\n }\n}\n\nimpl MyTrait for MyStruct1 {\n fn trait_func(&self) {\n // do something\n }\n}\n\nfn my_trait_fn(t: Rc<RefCell<MyTrait>>) {\n t.borrow_mut().trait_func();\n}\n\nfn main() {\n // (The type annotation is not necessary here, but helps explain it.\n // If the `my_str.borrow().my_fn()` line was missing, it would actually\n // be of type Rc<RefCell<MyTrait>> instead of Rc<RefCell<MyStruct1>>,\n // essentially doing the coercion one step earlier.)\n let my_str: Rc<RefCell<MyStruct1>> = Rc::new(RefCell::new(MyStruct1));\n my_trait_fn(my_str.clone());\n my_str.borrow().my_fn();\n}\nRun Code Online (Sandbox Code Playgroud)\n\n作为一般规则,看看是否可以使事物通过引用获取包含的值,理想情况下甚至可以通用 \xe2\x80\x94fn my_trait_fn<T: MyTrait>(t: &T)和类似的,通常可以通过自动引用和取消引用来调用,my_str.borrow()以处理其余的 \xe2\x80 \x94而不是整个Rc<RefCell<MyTrait>>事情。
| 归档时间: |
|
| 查看次数: |
2332 次 |
| 最近记录: |