我有一个队列Strategy
特性与Monotonic
和LastTick
的实现参数化我想要插入的类型:
struct Monotonic<T> {
items: Vec<T>,
}
struct LastTick<T> {
items: Vec<T>,
}
struct SetDelta;
trait Strategy<T> {
type T;
fn enqueue(&mut self, v: T);
fn has_pending(&self) -> bool;
}
impl<T> Strategy<T> for Monotonic<T> {
type T = Self;
fn enqueue(&mut self, v: T) {
self.items.push(v);
}
fn has_pending(&self) -> bool {
!self.items.is_empty()
}
}
impl<T> Strategy<T> for LastTick<T> {
type T = Self;
fn enqueue(&mut self, v: T) {
self.items.push(v);
}
fn has_pending(&self) -> bool {
!self.items.is_empty()
}
}
impl<T> Strategy<T> for LastTick<T> {
type T = Self;
fn enqueue(&mut self, v: T) {
self.items.push(v);
}
fn has_pending(&self) -> bool {
!self.items.is_empty()
}
}
impl<T> LastTick<T> {
fn new() -> Self {
LastTick { items: Vec::new() }
}
}
impl<T> Monotonic<T> {
fn new() -> Self {
Monotonic { items: Vec::new() }
}
}
#[test]
fn monotonic_scalar_queue() {
let mut a = Monotonic::<f64>::new();
a.enqueue(123.4);
assert!(a.has_pending());
}
#[test]
fn monotonic_list_queue() {
let mut a = Monotonic::<[f64; 3]>::new();
a.enqueue([123.4, 345.8, 324.1]);
assert!(a.has_pending());
}
#[test]
fn monotonic_tuple_queue() {
let mut a = Monotonic::<(f64, String, u32)>::new();
a.enqueue((123.4, "hello".into(), 324));
assert!(a.has_pending());
}
以上工作很好。我想为HashSet
保持相同的界面,其行为略有不同。
#[test]
fn monotonic_set_queue() {
let mut a = Monotonic::<HashSet<f64>>::new();
// I want to insert a f64 and implement the logic of the hashset in
// the implementation, but it expects a new HashSet
a.enqueue(123.4);
assert!(a.has_pending());
}
我试过了
impl<T> Strategy<T> for Monotonic<HashSet<f64>> {
type T = Self;
fn enqueue(&mut self, v: T) {
self.items.push(v);
}
fn has_pending(&self) -> bool {
!self.items.is_empty()
}
}
并且
impl Strategy<f64> for Monotonic<f64> {
type T = HashSet<f64>;
fn enqueue(&mut self, v: f64) {
self.items.push(v);
}
fn has_pending(&self) -> bool {
!self.items.is_empty()
}
}
结果不同,但没有运气。有没有办法轻松指定这个?
看起来你想要一个不同的Monotonic<T>
实现,其中的集合不是Vec
- 这是你现在定义Monotonic
的方式所不可能的。相反,您可以创建另一种类型MonotonicHashSet<T>
,并使用HashSet
作为后备集合。
相反,如果您想让Monotonic
接受不同的集合类型,那么您可能还想在集合类型上对其进行泛化。然而,这可能很快变得复杂。在Rust中,我们通常与集合关联的属性分为几个特征,在iter
module中定义。它们被拆分,以便每个集合类型可以针对集合所具有的任何约束精细且正确地定义它的行为。因此,对于您的Monotonic
和LastTick
类型,重要的是要考虑您可能具有哪些要求,以及这意味着您需要将集合用于该类型的特征。
最后一点说明:虽然Vec
接受任何类型的T
,但HashSet
需要通过Eq
特性从Hash
特征和可持续性完全平等。这些不同的要求值得考虑,因为与C#不同,Rust不为所有类型提供这些操作的默认实现 - 您必须提供它们或#[derive()]
them。