В настоящее время у меня есть такой код:
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
. В этом причина двух черт.
@kmdreko, это интересный момент, спасибо, что сообщили мне.
Апкастинговое принуждение пока не стабильно. Так что это может сработать +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();
}
Кстати, любой вызывающий
do_some_processing
по-прежнему сможет получить доступ к оригиналу какdyn Child
, поскольку здесь ничто не мешает им хранить оригиналArc
.