关于 Rust 中的泛型和特征的问题
Question about generics and traits in Rust
我有 DoSomethingProvider
特征,它期望其函数之一的参数是特征类型 DoSomethingListener
。
我有一个具体的结构 DoSomethingManager
,它有一个 DoSomethingProvider
类型的成员,并将实现 DoSomethingListener
特征并将其作为侦听器自身传递给 DoSomethingProvider
.
希望代码能够说明我正在尝试做的事情:
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 中实现这种多态代码的正确方法是什么?
我要编译的内容与解决此问题所需要做的事情相差不远,但我不喜欢这个解决方案。看来您 do 必须添加一个使用 PhantomData
.
类型的虚拟字段
更改 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.
使用动态调度
我有 DoSomethingProvider
特征,它期望其函数之一的参数是特征类型 DoSomethingListener
。
我有一个具体的结构 DoSomethingManager
,它有一个 DoSomethingProvider
类型的成员,并将实现 DoSomethingListener
特征并将其作为侦听器自身传递给 DoSomethingProvider
.
希望代码能够说明我正在尝试做的事情:
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 中实现这种多态代码的正确方法是什么?
我要编译的内容与解决此问题所需要做的事情相差不远,但我不喜欢这个解决方案。看来您 do 必须添加一个使用 PhantomData
.
更改 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.