Rust API Design: введите параметры для дополнительных значений - PullRequest
1 голос
/ 22 марта 2020

Я работаю над библиотекой Rust, которая предоставляет черту, которая может быть дополнительно реализована пользователем. Это может выглядеть так:

pub trait MyHandler {
    fn do_something(&mut self);
}

Основная структура в библиотеке выглядит примерно так:

pub struct MyType<H: MyHandler {
    field_a: u8,
    field_b: u32,
    handler: Option<H>,
}

Это работает, но на самом деле очень маленький процент пользователей будет реализовывать пользовательский обработчик. Проблема с точки зрения эргономики заключается в том, что тип H всегда нужно указывать, даже если в него не передается никакой обработчик:

let t = MyType {
    field_a: 1,
    field_b: 3000,
    handler: None,
};
error[E0282]: type annotations needed for `MyType<H>`
  --> src/main.rs:12:13
   |
12 |     let t = MyType {
   |         -   ^^^^^^ cannot infer type for type parameter `H` declared on the struct `MyType`
   |         |
   |         consider giving `t` the explicit type `MyType<H>`, where the type parameter `H` is specified

Все, что может сделать библиотека, чтобы упростить это , для обеспечения фиктивной реализации, которая может быть указана пользователем:

pub struct DefaultHandler {}

impl MyHandler for DefaultHandler {
    fn do_something(&mut self) {}
}
let t = MyType::<DefaultHandler> {
    field_a: 1,
    field_b: 3000,
    handler: None,
};

Есть ли хороший шаблон, чтобы сделать это более эргономичным c, без необходимости указывать фиктивную черту impl?

1 Ответ

1 голос
/ 22 марта 2020

Есть ли разница между None и Some(DefaultHandler)?

Если нет, я бы сделал handler типа H и, возможно, потребовал бы от пользователя указать DefaultHandler (вместо None).

Во-вторых, вы могли бы добавить функцию-конструктор new, которая просто создает MyType<DefaultHandler> с handler: DefaultHandler, и вы могли бы - в дополнение к этому и для абонентов, которые на самом деле хотят пользовательский handler - добавить функцию конструктора new_with_handler, которая принимает пользовательский обработчик в качестве аргумента, который затем используется для создания MyType с соответствующим handler. (Это несколько похоже на, например, HashMap::new (создание нового HashMap со значениями по умолчанию) и HashMap::with_hasher (создание нового HashMap с данным хэшем).)

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