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

需要泛型类型,但找到具体类型(实现特征绑定)

  •  3
  • manonthemat  · 技术社区  · 7 年前

    我有两种方法可以做非常相似的事情,我确实想使用泛型和特征边界进行重构。

    以下是我示例中的两种工作方法。

    fn some_method_a(some_arg: u8) -> (Mode, Vec<A>)
    {
        let mode = match some_arg {
            0 => Mode::ZERO,
            _ => Mode::NOTZERO,
        };
    
        let some_as = vec![A::new(0), A::new(1)];
        (mode, some_as)
    }
    
    fn some_method_b(some_arg: u8) -> (Mode, Vec<B>)
    {
        let mode = match some_arg {
            0 => Mode::ZERO,
            _ => Mode::NOTZERO,
        };
    
        let some_bs = vec![B::new("Testing".to_string())];
        (mode, some_bs)
    }
    

    这是应该取代两者的方法。

    fn some_method<T>(some_arg: u8) -> (Mode, Vec<T>)
    where
        T: Filterable,
    {
        let mode = match some_arg {
            0 => Mode::ZERO,
            _ => Mode::NOTZERO,
        };
    
        match &mode {
            &Mode::ZERO => (mode, vec![A::new(0), A::new(1)]),
            _ => (mode, vec![B::new("Testing".to_string())]),
        }
    }
    

    error[E0308]: mismatched types
      --> src/main.rs:11:36
       |
    11 |         &Mode::ZERO => (mode, vec![A::new(0), A::new(1)]),
       |                                    ^^^^^^^^^ expected type parameter, found struct `A`
       |
       = note: expected type `T`
                  found type `A`
    

    Permalink to playground 以下是程序的其余部分:

    #[derive(Debug)]
    enum Mode {
        ZERO,
        NOTZERO,
    }
    
    trait Filterable {
        fn get_some_data(&self) -> u8 {
            0
        }
    }
    
    struct A {
        some_data: u8,
    }
    
    struct B {
        some_other_data: String,
    }
    
    impl A {
        fn new(some_data: u8) -> A {
            A { some_data }
        }
    }
    
    impl B {
        fn new(some_other_data: String) -> B {
            B { some_other_data }
        }
    }
    
    impl Filterable for A {
        fn get_some_data(&self) -> u8 {
            self.some_data
        }
    }
    
    impl Filterable for B {}
    

    一些_方法需要做什么才能返回模式元组和a或B结构的向量?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Simon Whitehead    7 年前

    我对Rust泛型的理解是,它们比您可能习惯的更像C++模板,因为它们是单态的,并且在编译时进行扩展。

    基本上是这样:

    fn some_method<T>(some_arg: u8) -> (Mode, Vec<T>)
        where T: Filterable,
    

    ...是( )创建此方法的两个版本。期望返回的人 (Mode, Vec<A>) 一个期待回归的人 (Mode, Vec<B>)

    你想要的是返回一个实现特征的向量 Filterable . 因此,既然特征没有大小,你就需要把它们包起来 Box “在这里,给他们表演技巧:

    fn some_method(some_arg: u8) -> (Mode, Vec<Box<Filterable>>)
    

    这完全删除了泛型,只返回一个装箱向量 可过滤 -实现实例。

    match &mode {
        &Mode::ZERO => (mode, vec![Box::new(A::new(0)), Box::new(A::new(1))]),
        _ => (mode, vec![Box::new(B::new("Testing".to_string()))]),
    }
    

    导致代码编译。

    Here it is running on the Playground