如何克隆一个 Rc 特征对象并将其转换为另一个特征对象?
How do I clone a Rc trait object and cast it to another trait object?
这是 的后续问题。当我们对特征对象使用引用时,那里提供的解决方案非常有效,但这次我试图对 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
指针。
有没有办法转换克隆的共享指针?
methods as_a
and as_b
can't know self is actually an Rc
pointer.
事实上,那不是真的! 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>
(only Clone
). One way to fix this is to simply clone ab
before passing it into these methods. This also means that you don't need to clone the self
inside the method. (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
的情况下调用 ab.as_a()
。这种方法的唯一问题是 TraitAB
is no longer object-safe1, so Rc<dyn TraitAB>
no longer works. (playground link).
- 根据 the tracking issue for arbitrary self types,对象安全问题仍然悬而未决。我不太确定现在的规则是什么。
您需要在 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();
}
}
顺便说一句,我看不出 TraitAB
扩展 TraitA + TraitB
的任何理由,但您可以扩展和实现 TraitA
和 TraitB
Rc<MyType>
还有。
This is a working example 实现了 TraitA
和 TraitB
的功能。
这是 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
指针。
有没有办法转换克隆的共享指针?
methods
as_a
andas_b
can't know self is actually anRc
pointer.
事实上,那不是真的! 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>
Clone
). One way to fix this is to simply clone ab
before passing it into these methods. This also means that you don't need to clone the self
inside the method. (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
的情况下调用 ab.as_a()
。这种方法的唯一问题是 TraitAB
is no longer object-safe1, so Rc<dyn TraitAB>
no longer works. (playground link).
- 根据 the tracking issue for arbitrary self types,对象安全问题仍然悬而未决。我不太确定现在的规则是什么。
您需要在 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();
}
}
顺便说一句,我看不出 TraitAB
扩展 TraitA + TraitB
的任何理由,但您可以扩展和实现 TraitA
和 TraitB
Rc<MyType>
还有。
This is a working example 实现了 TraitA
和 TraitB
的功能。