如何为一个包含Rc<RefCell<Trait>>的结构体实现Deref?

5
我的目标是将结构体的方法调用委托给Trait的方法,其中Trait对象位于RefCell的Rc内部。
我尝试遵循这个问题的建议: How can I obtain an &A reference from a Rc<RefCell<A>>? 但是,我遇到了编译错误。
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::*;
use std::ops::Deref;

pub struct ShyObject {
    pub association: Rc<RefCell<dyn Display>>
}

impl Deref for ShyObject {
    type Target = dyn Display;
    fn deref<'a>(&'a self) -> &(dyn Display + 'static) {
        &*self.association.borrow()
    }
}

fn main() {}

以下是错误信息:

error[E0515]: cannot return value referencing temporary value
  --> src/main.rs:13:9
   |
13 |         &*self.association.borrow()
   |         ^^-------------------------
   |         | |
   |         | temporary value created here
   |         returns a value referencing data owned by the current function

我的示例使用 Display 作为特质(Trait)的实现;实际上,我有一个拥有十几个方法的 Trait。我想避免重复编写所有这些方法的模板代码,并且只需在每次调用中深入到 Trait 对象即可。


2
相关但可能不完全重复的问题:如何在不破坏封装的情况下返回RefCell中某个内容的引用?如何将RefCell<T>中的T作为引用借用?。请注意,这两个问题都通过返回实现Deref的智能指针的方法解决,而不是仅仅为主类型(在您的情况下为ShyObject)实现Deref - trent
2个回答

4

您不能这样做。borrow创建了一个新的结构用于跟踪借用的RefCell。因此,您不允许返回对该Ref的借用,因为它是局部变量。


有没有其他方法使用Deref来实现代理?通过一些有关生命周期的魔法? - Paul Chernoch
2
@PaulChernoch 生命周期注解不会改变事物的存活时间 - 它们只是向编译器描述您希望的生命周期限制。如果您想要不可能实现的限制,那么没有任何注解能够帮助到您。 - Peter Hall
1
@PaulChernoch 不行,根据定义你是不能的。 - Boiethios

4
您无法这样做。RefCell::borrow返回Ref<T>,而不是&T。如果您在方法中尝试这样做,则需要先借用Ref<T>,但它将超出范围。
不要实现Deref,而是可以编写一个返回相应内容的方法:
impl ShyObject {
    fn as_deref(&self) -> impl Deref<Target = dyn Display> {
        self.association.borrow()
    }
}

否则,由于您只想暴露内部数据的Display实现,因此可以通过实际取消引用委托的不同类型来解决它。
pub struct ShyObject {
    association: Assocation<dyn Display>,
}

struct Assocation<T: ?Sized>(Rc<RefCell<T>>);

impl<T: Display + ?Sized> fmt::Display for Assocation<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0.borrow())
    }
}

impl Deref for ShyObject {
    type Target = dyn Display + 'static;
    fn deref(&self) -> &Self::Target {
        &self.association
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接