【发布时间】:2019-09-21 09:14:26
【问题描述】:
此问题与Rust: Clone and Cast Rc pointer有关
假设我有这段代码可以正常工作:
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。 - 目标是让 trait 对象
TraitA能够转换为TraitB,反之亦然。 - 所以我使用了一个超特征来保存进行转换的方法。
- 这适用于
std::Rc智能指针。
到目前为止一切顺利。但现在我需要a 和b 的可变引用,但由于a 和b 实际上是同一个类型实例,Rust 不会让我有2 个相同事物的可变引用。
所以,这类问题的常见模式是std::cell::RefCell。
注意:我相信这种模式在这种特殊情况下是正确的,因为它是一个常见的内部可变性问题。我不愿意实际更改引用,而只更改类型的内部状态。
因此,按照这个想法,我更改了以下几行:
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{}));
但是这些更改不会编译。经过一番阅读,我发现self只能是:
self: Self // selfself: &Self // &selfself: &mut Self // &mut selfself: Box<Self> // No short formself: Rc<Self> // No short form / Recently supported
所以这意味着我不能使用
self: Rc<RefCell<Self>>
用于自参数。
所以,主要问题是:有没有办法将 Rc<RefCell<TraitA>> 转换为 Rc<RefCell<TraitB> ?
谢谢
【问题讨论】: