如何拥有动态的Box<dyn Trait<T,S>>?

How to have dynamic Box<dyn Trait<T,S>>?

我有 T 和 S 类型的交易列表,在 运行 时我想获取其详细信息。 如何具有结构的多个泛型类型的特征 我试过的代码如下所述:-

use std::fmt::Debug;
use std::any::Any;


#[derive(Debug)]
struct TransactionSet<T,S>{
    pub name: String,
    pub key:T,
    pub value:S

}

trait Details<T,S>{
    fn get_details(&self);

    fn get_key(&self)->&T;

    fn get_value(&self)->&S;
}

impl<T: Debug, S: Debug> Details<T,S> for TransactionSet<T, S> {
    fn get_details(&self) {
        println!("{:?} {:?} {:?}",self.name.to_string(),&self.key,&self.value)
    }
    fn get_key(&self)->&T {
        &self.key
    }

    fn get_value(&self)->&S {
        &self.value
    }

}



fn print_type_of<T>(_: &T) {
    println!("{}", std::any::type_name::<T>())
}

fn get<T: Any>(value: Box<dyn Any>) -> T {
    let pv = value.downcast().expect("The pointed-to value must be of type T");
    *pv
}



fn main() {
    //let mut vec: Vec<Box<dyn NewTrait<T:Debug,S:Debug>>> = Vec::new(); //Not working
    //  let mut vec: Vec<Box<dyn Details<T: Debug,S: Debug>>> = Vec::new();//Cannot use Details Trait
    let  vec: Vec<Box<dyn Details<_,_>>> = Vec::new();//Cannot use Details Trait

    let a1:TransactionSet<String,String> = TransactionSet { name: String::from("Test1"), key: String::from("name"), value: String::from("vinay") };
    let a2:TransactionSet<String,i32> = TransactionSet { name: String::from("Test2"), key: String::from("age"), value: 32_i32 };
    let a3 = TransactionSet { name: String::from("Test3"), key: 1_i32, value: 10_u64 };
    let a4 = TransactionSet { name: String::from("Test4"), key: String::from("isEligibleToVote"), value: true };

    //let a2 = ABC::new( String::from("Test2"), String::from("company"),  String::from("supra"));;

    vec.push(Box::<TransactionSet<String,String>>::new(a1));
    vec.push(Box::<TransactionSet<String,i32>>::new(a2));
    vec.push(Box::new(a3));
    vec.push(Box::new(a4));
    for v in vec.iter() {
        v.get_details();
        //  print_type_of(v);

        println!("Key : {:?}", v.get_key());
        println!("Value : {:?}", v.get_value());
    }

}

有没有其他方法可以解决这个问题? 就像 Vec<Box<dyn Details<?Unknown,?Unknown>>> 如果我删除特征详细信息的通用类型,我不能为它写 getter

Playground Link

你需要使用 dyn 来抽象到你需要的特征。

第一步是为你的特征添加类型,它不需要是通用的:

trait Details {
    type Key;
    type Value;
    fn get_details(&self);

    fn get_key(&self) -> &Self::Key;

    fn get_value(&self) -> &Self::Value;
}

然后你可以在一些通用的 TransactionSet 上实现特征,其中 bot TS 实现 Debug:

impl Details for TransactionSet<Box<dyn Debug>, Box<dyn Debug>> {
    type Key = Box<dyn Debug>;
    type Value = Box<dyn Debug>;
    fn get_details(&self) {
        println!(
            "{:?} {:?} {:?}",
            self.name.to_string(),
            &self.key,
            &self.value
        )
    }
    fn get_key(&self) -> &Self::Key {
        &self.key
    }

    fn get_value(&self) -> &Self::Value {
        &self.value
    }
}

请注意您的 TransactionSet 类型是 TransactionSet<Box<dyn Debug>, Box<dyn Debug>>

这是一个完整的工作示例:

use std::any::Any;
use std::fmt::Debug;

#[derive(Debug)]
struct TransactionSet<T, S> {
    pub name: String,
    pub key: T,
    pub value: S,
}

trait Details {
    type Key;
    type Value;
    fn get_details(&self);

    fn get_key(&self) -> &Self::Key;

    fn get_value(&self) -> &Self::Value;
}

impl Details for TransactionSet<Box<dyn Debug>, Box<dyn Debug>> {
    type Key = Box<dyn Debug>;
    type Value = Box<dyn Debug>;
    fn get_details(&self) {
        println!(
            "{:?} {:?} {:?}",
            self.name.to_string(),
            &self.key,
            &self.value
        )
    }
    fn get_key(&self) -> &Self::Key {
        &self.key
    }

    fn get_value(&self) -> &Self::Value {
        &self.value
    }
}

fn print_type_of<T>(_: &T) {
    println!("{}", std::any::type_name::<T>())
}

fn get<T: Any>(value: Box<dyn Any>) -> T {
    let pv = value
        .downcast()
        .expect("The pointed-to value must be of type T");
    *pv
}

fn main() {
    let mut vec: Vec<Box<dyn Details<Key = _, Value = _>>> = Vec::new(); //Cannot use Details Trait

    let a1: TransactionSet<Box<dyn Debug>, Box<dyn Debug>> = TransactionSet {
        name: String::from("Test1"),
        key: Box::new(String::from("name")),
        value: Box::new(String::from("vinay")),
    };
    let a2: TransactionSet<Box<dyn Debug>, Box<dyn Debug>> = TransactionSet {
        name: String::from("Test2"),
        key: Box::new(String::from("age")),
        value: Box::new(32_i32),
    };
    // let a3 = TransactionSet { name: String::from("Test3"), key: 1_i32, value: 10_u64 };
    // let a4 = TransactionSet { name: String::from("Test4"), key: String::from("isEligibleToVote"), value: true };

    vec.push(Box::<TransactionSet<Box<dyn Debug>, Box<dyn Debug>>>::new(
        a1,
    ));
    vec.push(Box::<TransactionSet<Box<dyn Debug>, Box<dyn Debug>>>::new(a2));
    // vec.push(Box::new(a3));
    // vec.push(Box::new(a4));
    for v in vec.iter() {
        v.get_details();
        //  print_type_of(v);

        println!("Key : {:?}", v.get_key());
        println!("Value : {:?}", v.get_value());
    }
}


Playground