这是来自Rust dynamic cast trait object between different taits的后续问题。当我们使用特征对象的引用时,那里提供的解决方案工作得很好,但是这次我尝试使用Rc
指针做同样的事情。例如
TraitAB
的超级特征和两个名为TraitA
和TraitB
的特征TraitAB
的特征对象而不是使用Box
时,现在我使用Rc
指针。TraitA
类型的变量作为ab
的引用这里我举了一个非常小的例子:
use std::rc::Rc;
trait TraitAB: TraitA + TraitB {
fn as_a(&self) -> Rc<dyn TraitA>;
fn as_b(&self) -> Rc<dyn TraitB>;
}
trait TraitA {}
trait TraitB {}
struct MyType {}
impl TraitAB for MyType {
fn as_a(&self) -> Rc<dyn TraitA> {
Rc::clone(self)
}
fn as_b(&self) -> Rc<dyn TraitB> {
Rc::clone(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.as_a();
b = ab.as_b();
}
}
虽然这不起作用。根据错误信息:
error[E0308]: mismatched types
--> src/main.rs:15:19
|
15 | Rc::clone(self)
| ^^^^ expected struct `std::rc::Rc`, found struct `MyType`
|
= note: expected reference `&std::rc::Rc<dyn TraitA>`
found reference `&MyType`
error[E0308]: mismatched types
--> src/main.rs:18:19
|
18 | Rc::clone(self)
| ^^^^ expected struct `std::rc::Rc`, found struct `MyType`
|
= note: expected reference `&std::rc::Rc<dyn TraitB>`
found reference `&MyType`
[as_a
和as_b
]不能知道self实际上是Rc
指针。有没有办法对克隆的共享指针进行强制转换?
as_a
和as_b
方法不知道self实际上是Rc
指针。
实际上,这是不正确的! a rarely used feature允许将self
用作各种标准种类的引用(Rc<Self>
,Box<Self>
等)。
这意味着您可以将TraitAB
重写为
trait TraitAB : TraitA + TraitB {
fn as_a(self: Rc<Self>) -> Rc<dyn TraitA>;
fn as_b(self: Rc<Self>) -> Rc<dyn TraitB>;
}
[不幸的是,由于as_a
as_b
(仅self: Rc<Self>
),Rc<T>
和doesn't implement Copy
会移动Copy
。解决此问题的一种方法是在将Clone
传递给这些方法之前,先对其进行克隆。这也意味着您无需在方法内部克隆ab
。 self
(playground link)
使用仅夜间功能let ab: Rc<dyn TraitAB> = Rc::new(MyType{});
let _a: Rc<dyn TraitA> = ab.clone().as_a();
let _b: Rc<dyn TraitB> = ab.clone().as_b();
,可以使arbitrary_self_types
和as_a
取为as_b
(这对我来说很奇怪,因为它是对参考的引用)。这样就可以在不移动&Rc<Self>
的情况下调用ab.as_a()
。这种方法的唯一问题是ab
TraitAB
1,因此is no longer object-safe不再起作用。 Rc<dyn TraitAB>
。
您需要在the tracking issue for arbitrary self types上实现TraitAB
:
RC<MyType>
顺便说一句,我看不到use std::rc::Rc;
trait TraitAB {
fn as_a(&self) -> Rc<dyn TraitA>;
fn as_b(&self) -> Rc<dyn TraitB>;
}
trait TraitA {}
trait TraitB {}
struct MyType {}
impl TraitAB for Rc<MyType> {
fn as_a(&self) -> Rc<dyn TraitA> {
Rc::clone(self) as Rc<dyn TraitA>
}
fn as_b(&self) -> Rc<dyn TraitB> {
Rc::clone(self) as Rc<dyn TraitB>
}
}
impl TraitA for MyType {}
impl TraitB for MyType {}
fn main() {
let a: Rc<dyn TraitA>;
let b: Rc<dyn TraitB>;
{
let mut ab: &TraitAB = &Rc::new(MyType {});
a = ab.as_a();
b = ab.as_b();
}
}
扩展TraitAB
的任何理由,但是您也可以扩展并实现TraitA + TraitB
和TraitA
为TraitB
。
Rc<MyType>
具有已实现的This is a working example和TraitA
功能。