Вопрос о дженериках и чертах в Rust - PullRequest
0 голосов
/ 05 мая 2019

У меня есть черта 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?

Ответы [ 2 ]

0 голосов
/ 05 мая 2019

Измените DoSomethingProvider, чтобы использовать связанный тип вместо параметра типа для типа слушателя.

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 .

0 голосов
/ 05 мая 2019

То, что я получил для компиляции, не далеко от того, что нужно сделать, чтобы решить эту проблему, но мне не нравится решение.Кажется, вам do необходимо добавить фиктивное поле, которое использует тип с PhantomData.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...