[英]How do I clone a Rc trait object and cast it to another trait object?
這是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
指針。
其實,那不是真的! 有一個很少使用的功能允許將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>
沒有實現Copy
(只有Clone
)。 解決此問題的一種方法是在將ab
傳遞給這些方法之前簡單地克隆它。 這也意味着您不需要在方法內部克隆self
。 (游樂場鏈接)
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
將 self 視為&Rc<Self>
(這對我來說看起來很奇怪,因為它是對引用的引用)。 這允許在不移動ab
的情況下調用ab.as_a()
。 這種方法的唯一問題是TraitAB
不再是對象安全的1 ,因此Rc<dyn TraitAB>
不再有效。 (游樂場鏈接) 。
您需要在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
,但您也可以為Rc<MyType>
擴展和實現TraitA
和TraitB
。
這是一個工作示例,其中包含TraitA
和TraitB
的已實現功能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.