关于Rust中的泛型和特征的问题

时间:2019-05-05 17:46:24

标签: generics rust traits

我具有DoSomethingProvider特质,期望其功能之一的参数具有特质类型DoSomethingListener

我有一个具体的结构DoSomethingManager,其成员类型为DoSomethingProvider,并将实现DoSomethingListener特征并将其作为侦听器自身传递给DoSomethingProvider。 / p>

希望代码可以说明我正在尝试做的事情:

pub trait DoSomethingListener {
    fn something_was_done(msg: &str);
}

pub trait DoSomethingProvider<'a, T>
where
    T: DoSomethingListener,
{
    fn add_do_something_listener(listener: T);
}

/* note:  The struct below will implement DoSomethingListener, and has
 * a DoSomethingProvider field.  It will pass itself as a listener to
 * DoSomethingProvider (which listens to a message queue and notifies
 * listeners of certain events)
 */

//this doesn't work.  Compiler complains about unused type T
pub struct DoSomethingManager<'a, B, T>
where
    T: DoSomethingListener,
    B: DoSomethingProvider<'a, T>,
{
    provider: Box<B>,
    // doesn't have any member of type T
}

// ...

/* So I tried this:
 * this doesn't work.  Compiler complains that DoSomethingProvider
 * expects one type parameter
 */
pub struct DoSomethingManager<'a, B>
where
    B: DoSomethingProvider<'a>,
{
    provider: Box<B>,
    // doesn't have any member of type T
}

//...

/* this compiles, but its a hack */
pub struct DoSomethingManager<'a, B, T>
where
    T: DoSomethingListener,
    B: DoSomethingProvider<'a, T>,
{
    provider: Box<B>,
    dummy: Box<T>,
    // added unused dummy member of type T
}

我是一位经验丰富的Python开发人员,但是我是Rust的新手。在Rust中实现这种多态代码的正确方法是什么?

2 个答案:

答案 0 :(得分:0)

我要编译的内容与解决此问题并不遥远,但是我不喜欢这种解决方案。看来您要做必须添加一个使用PhantomData类型的虚拟字段。

答案 1 :(得分:0)

更改DoSomethingProvider以使用associated type代替侦听器类型的类型参数。

pub trait DoSomethingListener {
    fn something_was_done(msg: &str);
}

pub trait DoSomethingProvider {
    type Listener: DoSomethingListener;

    fn add_do_something_listener(listener: Self::Listener);
}

pub struct DoSomethingManager<B>
where
    B: DoSomethingProvider,
{
    provider: Box<B>,
}

请注意,通过使用关联的类型或类型参数,DoSomethingProvider的特定实例将只能接受单个特定类型的侦听器。如果您希望能够注册各种类型的侦听器,则需要通过trait objects使用动态调度。