代码之家  ›  专栏  ›  技术社区  ›  ZNackasha

如何将Arc<RwLock<dyn Child>>转换为Arc<RwLock<dyn-Base>>

  •  0
  • ZNackasha  · 技术社区  · 10 月前

    我目前有一些代码如下:

    use std::sync::{Arc, RwLock};
    
    // Define traits
    trait Child: Base {
        fn method_a(&self);
    }
    
    trait Base {
        fn method_b(&self);
    }
    
    // Struct implementing both traits
    struct MyStruct {
        something: i32,
    };
    
    impl Child for MyStruct {
        fn method_a(&self) {
            println!("Method A");
        }
    }
    
    impl Base for MyStruct {
        fn method_b(&self) {
            println!("Method B");
        }
    }
    
    fn do_some_processing(parent: &Arc<RwLock<dyn Child>>) -> Arc<RwLock<dyn Base>> {
        //How do i do this?
    }
    
    fn main() {
        let my_struct = Arc::new(RwLock::new(MyStruct));
    
        let base = do_some_processing(&my_struct);
    
    }
    

    我想限制之后使用的功能 do_some_processing 已被召唤。这就是这两个特征的原因。

    1 回复  |  直到 10 月前
        1
  •  1
  •   Milan Jaric    10 月前

    Upcasting coercion 还不稳定。所以这可以在 +nightly

    #![feature(trait_upcasting)]
    use std::sync::{Arc, RwLock};
    
    // Define traits
    trait Child: Base {
        fn method_a(&self);
    }
    
    trait Base {
        fn method_b(&self);
    }
    
    // Struct implementing both traits
    struct MyStruct {
        something: i32,
    }
    
    impl Child for MyStruct {
        fn method_a(&self) {
            println!("Method A");
        }
    }
    
    impl Base for MyStruct {
        fn method_b(&self) {
            println!("Method B");
        }
    }
    
    fn do_some_processing(parent: &Arc<RwLock<dyn Child>>) -> Arc<RwLock<dyn Base>> {
        parent.clone()
    }
    
    
    
    fn main() {
        let my_struct: Arc<RwLock<dyn Child>> = Arc::new(RwLock::new(MyStruct { something: 42 }));
    
        let base = do_some_processing(&my_struct);
    
    }
    

    ---或---

    如果你想坚持稳定,你需要一些包装材料

    use std::sync::{Arc, RwLock};
    
    // Define traits
    trait Child: Base {
        fn method_a(&self);
    }
    
    trait Base {
        fn method_b(&self);
    }
    
    // Struct implementing both traits
    struct MyStruct {
        something: i32,
    }
    
    impl Child for MyStruct {
        fn method_a(&self) {
            println!("Method A");
        }
    }
    
    impl Base for MyStruct {
        fn method_b(&self) {
            println!("Method B");
        }
    }
    
    // Wrapper struct to manually upcast Child to Base
    struct BaseWrapper {
        inner: Arc<RwLock<dyn Child>>,
    }
    
    impl Base for BaseWrapper {
        fn method_b(&self) {
            self.inner.read().unwrap().method_b();
        }
    }
    
    fn upcast(child: Arc<RwLock<dyn Child>>) -> Arc<RwLock<dyn Base>> {
        Arc::new(RwLock::new(BaseWrapper { inner: child }))
    }
    
    fn main() {
        let my_struct: Arc<RwLock<dyn Child>> = Arc::new(RwLock::new(MyStruct { something: 42 }));
    
        let base = upcast(my_struct);
    
        base.read().unwrap().method_b();
    }