我可以在嵌套类型上专门化特征吗?

问题描述 投票:0回答:1

我有一个队列Strategy特性与MonotonicLastTick的实现参数化我想要插入的类型:

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()
    }
}

结果不同,但没有运气。有没有办法轻松指定这个?

rust
1个回答
1
投票

看起来你想要一个不同的Monotonic<T>实现,其中的集合不是Vec - 这是你现在定义Monotonic的方式所不可能的。相反,您可以创建另一种类型MonotonicHashSet<T>,并使用HashSet作为后备集合。

相反,如果您想让Monotonic接受不同的集合类型,那么您可能还想在集合类型上对其进行泛化。然而,这可能很快变得复杂。在Rust中,我们通常与集合关联的属性分为几个特征,在iter module中定义。它们被拆分,以便每个集合类型可以针对集合所具有的任何约束精细且正确地定义它的行为。因此,对于您的MonotonicLastTick类型,重要的是要考虑您可能具有哪些要求,以及这意味着您需要将集合用于该类型的特征。

最后一点说明:虽然Vec接受任何类型的T,但HashSet需要通过Eq特性从Hash特征和可持续性完全平等。这些不同的要求值得考虑,因为与C#不同,Rust不为所有类型提供这些操作的默认实现 - 您必须提供它们或#[derive()] them

© www.soinside.com 2019 - 2024. All rights reserved.