![](/img/trans.png)
[英]How do I clone a Rc trait object and cast it to another trait object?
[英]Clone an Rc<RefCell<MyType> trait object and cast it
這個問題與Rust有關:Clone和Cast Rc指針
假設我有一段運行良好的代碼:
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
。 TraitA
能夠TraitB
轉換為TraitB
,反之亦然。 std::Rc
智能指針非常std::Rc
。 到現在為止還挺好。 但現在我需要兩者的可變參考a
和b
,但由於a
和b
實際上是同一類型的情況下,防銹不會讓我有一樣的東西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
self: &Self // &self
self: &mut Self // &mut self
self: Box<Self> // No short form
self: Rc<Self> // No short form / Recently supported
所以這意味着我不能使用
self: Rc<RefCell<Self>>
對於自我的參數。
因此,主要問題是:是否有一種方法可以將Rc<RefCell<TraitA>>
轉換為Rc<RefCell<TraitB>
? 謝謝
您可以通過不在 TraitAB
的轉換方法中使用接收器(即,通過將它們聲明為關聯函數 )來解決此問題:
trait TraitAB : TraitA + TraitB {
fn as_a(it: Rc<RefCell<Self>>) -> Rc<RefCell<dyn TraitA>>;
fn as_b(it: Rc<RefCell<Self>>) -> Rc<RefCell<dyn TraitB>>;
}
然后可以將特征實現為
impl TraitAB for MyType {
fn as_a(it: Rc<RefCell<MyType>>) -> Rc<RefCell<dyn TraitA>> {it}
fn as_b(it: Rc<RefCell<MyType>>) -> Rc<RefCell<dyn TraitB>> {it}
}
然后可以使用完全限定的語法來調用這些函數。
a = TraitAB::as_a(ab.clone());
b = TraitAB::as_b(ab.clone());
所有類型的TraitAB
實現都是相同的。 為了使該實現可用於實現TraitA
和TraitB
所有類型,可以使用通用的impl
:
impl<T: TraitA + TraitB + 'static> TraitAB for T {
fn as_a(it: Rc<RefCell<T>>) -> Rc<RefCell<dyn TraitA>> {it}
fn as_b(it: Rc<RefCell<T>>) -> Rc<RefCell<dyn TraitB>> {it}
}
注意T: 'static
因為函數返回類型中的trait對象具有隱式的'static
生命周期限制。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.