如何创建以特征为返回参数的特征方法?

时间:2018-11-06 01:50:03

标签: rust

我有一个特征B,它定义了一个函数,该函数返回对实现特征A的对象的引用。

enum Error { }

trait A { }

trait B {
    fn create_a<'a>() -> Result<&'a impl A, Error>;
}

但是,当我尝试compile时,出现以下错误

error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
  --> src/lib.rs:10:37
   |
10 |     fn create_a<'a>() -> Result<&'a impl A, Error>;
   |                                     ^^^^^^

2 个答案:

答案 0 :(得分:6)

  

fn create_a<'a>() -> Result<&'a impl A, Error>;

如果没有对象已经具有该生存期并且可以充当其拥有者的对象,则无法创建可以任意生存的生存期的引用,而且您根本没有对象,因此该签名没有任何意义

对于进一步的论证,我将假设您确实有一个self自变量,并且存在生命周期(它可能也需要可变):fn create_a<'a>(&'a mut self) -> Result<&'a impl A, Error>;

(请注意,由于所有提及的参考文献只有一个生命周期,因此您可以忽略它:fn create_a(&mut self) -> Result<&impl A, Error>;

现在有两个选择:

  • 您可以将具体类型定义为该特征的成员,例如

    trait B {
        type ImplA: A;
        fn create_a(&mut self) -> Result<&ImplA, Error>;
    }
    

    这不是对象安全的,但是它将被静态调度。

    在实现特征时,如果需要,您应该能够使用impl类型别名。

  • 如果您确实希望B是对象安全的,请使用对象引用,即

    trait B {
        fn create_a(&mut self) -> Result<&dyn A, Error>;
    }
    

    这种向返回值进行分配的方式始终是动态的,但是您要这样做是为了始终允许动态对B::create_a进行分配。

答案 1 :(得分:-1)

有多种返回特征的方法,它们都依赖某种间接性。

  1. 您可以返回Box<A>
  2. 您可以返回Rc<A> / Arc<A>
  3. 您可以使用&dyn A
  4. 您可以使用类型参数T

1、2、3和4之差为static vs dynamic dispatching