簡體   English   中英

克隆RC <RefCell<MyType> 特征對象並進行投射

[英]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類型,它實現了TraitATraitB
  • 目標是使特征對象TraitA能夠TraitB轉換為TraitB ,反之亦然。
  • 因此,我使用一個上級特征來保存進行轉換的方法。
  • 這對於std::Rc智能指針非常std::Rc

到現在為止還挺好。 但現在我需要兩者的可變參考ab ,但由於ab實際上是同一類型的情況下,防銹不會讓我有一樣的東西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實現都是相同的。 為了使該實現可用於實現TraitATraitB所有類型,可以使用通用的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM