繁体   English   中英

如何从RefCell借用T. <T> 作为参考?

[英]How to borrow the T from a RefCell<T> as a reference?

有时我有一个包含在RefCell中的值的struct ,我想借用该值,但我不想让访问器函数的签名依赖于内部实现。 为了使它工作,我需要将引用作为Ref<T>而不是&T

例如,如果这是我的结构:

use std::cell::RefCell;

pub struct Outer<T> {
    inner: RefCell<T>,
}

我可以写一个这样的访问器:

use std::cell::Ref;

impl<T> Outer<T> {
    fn get_inner_ref(&self) -> Ref<T> {
        self.inner.borrow()
    }
}

这很好用。 我可以像这样使用它:

fn main() {
    let outer = Outer { inner: RefCell::new(String::from("hi")) };
    let inner: &str = &outer.get_inner_ref();
    println!("inner value = {:?}", inner);
}

但是,这会将Ref公开为公共API的一部分,这会使以后更改内部结构变得更加困难,而不会破坏向后兼容性。

如果我尝试更改签名以返回&T - &Ref<T>可以强制执行 - 那么我会遇到终身错误:

impl<T> Outer<T> {
    fn get_inner_ref(&self) -> &T {
        &self.inner.borrow()
    }
}

错误是:

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:16:10
   |
16 |         &self.inner.borrow()
   |          ^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
17 |     }
   |     - temporary value only lives until here
   |
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 15:5...
  --> src/main.rs:15:5
   |
15 | /     fn get_inner_ref(&self) -> &T {
16 | |         &self.inner.borrow()
17 | |     }
   | |_____^

似乎没有办法解决这个问题,因为错误消息是正确的。 代码试图引用Ref<T> ,它只持续函数调用。 为了使这个工作,我必须通过返回它来移出Ref<T>本身 - 就像在上面的原始代码中一样 - 而不是对它进行新的引用。

一个答案如何在不破坏封装的情况下返回对RefCell内部内容的引用? 这在技术上可以解决这个问题,但它是一个更专业的案例(只能获得RefCell的一部分价值),对于这种简单的情况,解决方案似乎过于复杂。

这正是impl Trait的目的, 从版本1.26开始就可以在稳定的Rust中使用。

use std::ops::Deref;

impl<T> Outer<T> {
    fn get_inner_ref<'a>(&'a self) -> impl Deref<Target = T> + 'a {
        self.inner.borrow()
    }
}

Rust编译器知道实际的实现是Ref<T>但是你可以避免显式写它,并且这个函数的调用者只能使用Deref特性提供的功能。

只要您返回的实际值是实现Deref<Target = T> ,您就可以在以后更改该实现而不会破坏任何使用它的代码。 例如,您可以返回&T其他几种引用类型之一 ,包括您自己的自定义类型,就像在另一个链接的问题中一样

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM