[英]How do I clone a Rc trait object and cast it to another trait object?
This is a follow up question from Rust dynamic cast trait object between different taits .这是Rust dynamic cast trait object between different taits的后续问题。 The solution provided there works really well when we use references for trait objects, but this time I am trying to do the same with Rc
pointers.当我们对特征对象使用引用时,那里提供的解决方案非常有效,但这次我试图对Rc
指针做同样的事情。 For example例如
TraitAB
and 2 traits named TraitA
and TraitB
我有一个名为TraitAB
的超级特征和两个名为TraitA
和TraitB
的特征TraitAB
instead of using a Box
, now I use an Rc
pointer.因此,当我第一次创建TraitAB
类型的特征对象而不是使用Box
时,现在我使用Rc
指针。TraitA
to be a reference of ab
我需要一个TraitA
类型的变量作为ab
的引用Here I made a very minimal example:在这里我做了一个非常小的例子:
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();
}
}
This doesn't work though.但这不起作用。 According to the error messages:根据错误信息:
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
and as_b
can't know self is actually an Rc
pointer. as_a
和as_b
无法知道 self 实际上是一个Rc
指针。 Is there a way to do the cast of a cloned shared pointer?有没有办法转换克隆的共享指针?
methods
as_a
andas_b
can't know self is actually anRc
pointer.方法as_a
和as_b
无法知道 self 实际上是一个Rc
指针。
Actually, that's not true!其实,那不是真的! There's a rarely used feature that allows self
to be taken as various standard kinds of references ( Rc<Self>
, Box<Self>
, etc.).有一个很少使用的功能允许将self
视为各种标准类型的引用( Rc<Self>
、 Box<Self>
等)。
That means that you can rewrite your TraitAB
as这意味着您可以将TraitAB
重写为
trait TraitAB : TraitA + TraitB {
fn as_a(self: Rc<Self>) -> Rc<dyn TraitA>;
fn as_b(self: Rc<Self>) -> Rc<dyn TraitB>;
}
Unfortunately, as written, as_a
and as_b
move self: Rc<Self>
, since Rc<T>
doesn't implement Copy
(only Clone
).不幸的是,正如所写的那样, as_a
和as_b
移动self: Rc<Self>
,因为Rc<T>
没有实现Copy
(只有Clone
)。 One way to fix this is to simply clone ab
before passing it into these methods.解决此问题的一种方法是在将ab
传递给这些方法之前简单地克隆它。 This also means that you don't need to clone the self
inside the method.这也意味着您不需要在方法内部克隆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();
Using the nightly-only feature arbitrary_self_types
, it's possible to make as_a
and as_b
take self as &Rc<Self>
(which looks weird to me since it's a reference to a reference).使用仅夜间功能arbitrary_self_types
,可以使as_a
和as_b
将 self 视为&Rc<Self>
(这对我来说看起来很奇怪,因为它是对引用的引用)。 This allows ab.as_a()
to be called without moving ab
.这允许在不移动ab
的情况下调用ab.as_a()
。 The only problem with this approach is that TraitAB
is no longer object-safe 1 , so Rc<dyn TraitAB>
no longer works.这种方法的唯一问题是TraitAB
不再是对象安全的1 ,因此Rc<dyn TraitAB>
不再有效。 (playground link) . (游乐场链接) 。
You need to implement TraitAB
on RC<MyType>
:您需要在RC<MyType>
上实施TraitAB
:
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();
}
}
By the way, I don't see any reason for TraitAB
to extend TraitA + TraitB
, but you can extend and implement TraitA
and TraitB
for Rc<MyType>
as well.顺便说一句,我看不出有任何理由让TraitAB
扩展TraitA + TraitB
,但您也可以为Rc<MyType>
扩展和实现TraitA
和TraitB
。
This is a working example with the implemented functions for TraitA
and TraitB
. 这是一个工作示例,其中包含TraitA
和TraitB
的已实现功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.