克隆Rc< RefCell< MyType>特征对象并对其进行投射 [英] Clone an Rc<RefCell<MyType> trait object and cast it

查看:75
本文介绍了克隆Rc< RefCell< MyType>特征对象并对其进行投射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题与 Rust:克隆和Cast Rc指针

假设我有一段运行良好的代码:

Let's say I have this piece of code which works fine:

use std::rc::Rc;

trait TraitAB : TraitA + TraitB {
    fn as_a(self: Rc<Self>) -> Rc<dyn TraitA>;
    fn as_b(self: Rc<Self>) -> Rc<dyn TraitB>;
}

trait TraitA {}
trait TraitB {}

struct MyType {}

impl TraitAB for MyType {
    fn as_a(self: Rc<Self>) -> Rc<dyn TraitA> {self}
    fn as_b(self: Rc<Self>) -> Rc<dyn TraitB> {self}
}

impl TraitA for MyType {}
impl TraitB for MyType {}

fn main() {
    let a: Rc<dyn TraitA>;
    let b: Rc<dyn TraitB>;
    {
        let mut ab: Rc<dyn TraitAB> = Rc::new(MyType{});
        a = ab.clone().as_a();
        b = ab.clone().as_b();
    }
    // Use a and b.
}

稍微解释一下代码:

  • 我有一个名为 MyType 的类型,它实现了 TraitA TraitB .
  • 目标是使特征对象 TraitA 能够转换为 TraitB ,反之亦然.
  • 因此,我使用一个超级特征来保存进行转换的方法.
  • 这对于 std :: Rc 智能指针非常有用.
  • I have type called MyType which implements TraitA and TraitB.
  • The goal is to have a trait object TraitA be able to get casted to TraitB and viceversa.
  • So I uses a supertrait that holds the methods to do the conversions.
  • This works great for std::Rc smart pointers.

到目前为止,一切都很好.但是现在我需要对 a b 进行可变引用,但是由于 a b 实际上是相同的类型实例,Rust不会让我对同一事物有2个可变引用.

So far so good. But now I need a mutable reference of both a and b, but since a and bare actually the same type instance, Rust won't let me have 2 mutable references of the same thing.

因此,此类问题的常见模式是 std :: cell :: RefCell .

So, the common pattern for this kind of problems is std::cell::RefCell.

注意:我认为这种模式在特定情况下是正确的,因为它是常见的内部可变性问题.我不愿意实际更改引用,而只更改类型的内部状态.

Note: I believe this pattern is correct in this particular case because it's a common interior mutability problem. I'm not willing to actually change the reference, but the internal state of the type only.

因此,按照这个想法,我更改了以下几行:

So following that idea I changed the following lines:

trait TraitAB : TraitA + TraitB {
    fn as_a(self: Rc<RefCell<Self>>) -> Rc<RefCell<dyn TraitA>>;
    fn as_b(self: Rc<RefCell<Self>>) -> Rc<RefCell<dyn TraitB>>;
}
//...
let mut ab: Rc<RefCell<dyn TraitAB>> = Rc::new(RefCell::new(MyType{}));

但是此更改不会编译.经过一番阅读,我发现自我只能是:

But this changes won't compile. After some reading, I found that self can only be:

  • self:自我//自我
  • self:& Self//& self
  • self:& mut self//& mut self
  • self:Box< Self>//没有简短格式
  • self:Rc< Self>//没有简短格式/最近支持

所以这意味着我不能使用

So this means I can't use

自身:Rc< RefCell< Self>>

关于自我参数.

因此,主要问题是:是否有一种方法可以将 Rc< RefCell< TraitA>> 转换为 Rc< RefCell< TraitB> ?谢谢

So, the main question is: Is there a way to cast an Rc<RefCell<TraitA>> to an Rc<RefCell<TraitB> ? Thanks

推荐答案

您可以使用 TraitAB 的转换方法(例如,通过将它们声明为关联函数):

You can work around this issue by not using a receiver in TraitAB's casting methods (i.e. by declaring them as associated functions):

trait TraitAB : TraitA + TraitB {
    fn as_a(it: Rc<RefCell<Self>>) -> Rc<RefCell<dyn TraitA>>;
    fn as_b(it: Rc<RefCell<Self>>) -> Rc<RefCell<dyn TraitB>>;
}

特征可以被实现为

impl TraitAB for MyType {
    fn as_a(it: Rc<RefCell<MyType>>) -> Rc<RefCell<dyn TraitA>> {it}
    fn as_b(it: Rc<RefCell<MyType>>) -> Rc<RefCell<dyn TraitB>> {it}
}

然后可以使用完全限定的语法来调用这些函数.

These functions can then be called using the fully qualified syntax.

a = TraitAB::as_a(ab.clone());
b = TraitAB::as_b(ab.clone());

所有类型的 TraitAB 实现都是相同的.要使此实现可用于所有实现 TraitA TraitB 的类型,可以使用通用的 impl :

The TraitAB implementation for all types will be the same. To make this implementation available for all types implementing TraitA and TraitB, you can use a generic impl:

impl<T: TraitA + TraitB + 'static> TraitAB for T {
    fn as_a(it: Rc<RefCell<T>>) -> Rc<RefCell<dyn TraitA>> {it}
    fn as_b(it: Rc<RefCell<T>>) -> Rc<RefCell<dyn TraitB>> {it}
}

请注意 T:'static ,因为函数返回类型中的特征对象具有隐式的'static 生命周期约束.

Note that T: 'static because the trait objects in the function return types have an implicit 'static lifetime bound.

游乐场

这篇关于克隆Rc&lt; RefCell&lt; MyType&gt;特征对象并对其进行投射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆