#collections #rust #extends
#Коллекции #Ржавчина #расширяет
Вопрос:
Я хочу реализовать VecDeque с максимальным ограничением размера. У меня есть две стратегии, но я не могу выполнить ни одну.
Первый подход: наследование по составу.
Я создал новую структуру:
pub struct LimVecDeque<T> {
deque: VecDeque<T>,
limit: usize,
}
И создайте новую функцию push:
impl<T> LimVecDeque<T> {
...
pub fn push (amp;self, elem: T) {
self.deque.push_back(elem);
if self.limit < self.deque.len() {
self.deque.pop_front();
}
}
...
}
Это работает, но по мере роста моей программы мне требуется добавить функциональность в мою структуру LimVecDeque. Большинство из них является копией исходного VecDeque:
pub fn len(amp;self) -> usize {
self.deque.len()
}
У меня больше проблем с экспортом VecDeque ::iter(). У меня были проблемы с типами и итераторами (я пока не очень хорошо разбираюсь в итераторах).
Этот подход заставляет меня клонировать / экспортировать каждую функцию в VecDeque в LimVecDeque. Много работы!
Второй подход: создайте новый признак и реализуйте для VecDeque:
trait Limited {
type Elem;
pub fn push_bounded(amp;self, limit: usize, elem: Elem);
}
и позже реализовать признак с помощью VecDeque.
Но я должен передавать limit
значение при каждой вставке. Как можно передать предельное значение один раз?
В общем, каков простой способ добавить функциональность в структуру из std (без потери / скрытия текущих)?
Ответ №1:
Как указано в ответе edkeveked, существует доступный crate ( BoundedVecDequeue
) , который реализует именно тот случай, который вы пытаетесь реализовать.
Если вы посмотрите на реализацию BoundedVecDequeue
, вы увидите, что она использует первый шаблон, который вы описываете: для создания методов-оболочек, где необходимо изменить поведение обернутого типа, и для делегирования вызовов методов, где это не так.
Как вы указываете, это может привести к большому количеству шаблонов. Чтобы уменьшить объем работы, вы можете попробовать delegate crate, который добавляет макрос, который выполняет делегирование за вас:
use delegate::delegate;
impl<T> LimVecDeque<T> {
delegate! {
to self.inner {
pub fn len(amp;self) -> usize;
pub fn truncate(amp;mut self, new_len: usize);
pub fn as_mut_slices(amp;mut self) -> (amp;mut [T], amp;mut [T]);
// etc
}
}
// ...
}
Предостережение: я сам еще не использовал этот ящик, поэтому не могу ручаться за его качество.
Ответ №2:
BoundedVecDeque
делает именно это
use ::bounded_vec_deque::BoundedVecDeque;
fn main() {
let mut a = BoundedVecDeque::new(2);
a.push_front(2);
a.push_front(3);
a.push_front(4);
println!("{:?}", a); //4, 3
}