简体   繁体   English

为实现 trait 的所有类型实现 trait

[英]Implement a trait for all types implementing a trait

I have this issue:我有这个问题:

  • multiple structs implementing a trait Event实现 trait Event多个结构
  • all can implement PartialEq trait the same way都可以用同样的方式实现PartialEq trait

I considered writing this (short version)我考虑过写这个(简短版本)

type Data = Vec<u8>;

trait Event {
    fn data(&self) -> &Data;
}

struct NoteOn {
    data: Data,
}
struct NoteOff {
    data: Data,
}
impl Event for NoteOn {
    fn data(&self) -> &Data {
        &self.data
    }
}
impl Event for NoteOff {
    fn data(&self) -> &Data {
        &self.data
    }
}
impl<T: Event> PartialEq for T {
    fn eq(&self, b: &T) -> bool {
        self.data() == b.data()
    }
}

fn main() {
    println!("Hello, world!");
}

playground 操场

This fails to compile:这无法编译:

error[E0119]: conflicting implementations of trait `std::cmp::PartialEq<&_>` for type `&_`:
  --> src/main.rs:23:1
   |
23 | impl<T: Event> PartialEq for T {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `core`:
           - impl<A, B> std::cmp::PartialEq<&B> for &A
             where A: std::cmp::PartialEq<B>, A: ?Sized, B: ?Sized;
   = note: downstream crates may implement trait `Event` for type `&_`

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
  --> src/main.rs:23:1
   |
23 | impl<T: Event> PartialEq for T {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
   |
   = note: only traits defined in the current crate can be implemented for a type parameter

What is wrong here?这里有什么问题? Or is there another way to implement generically this PartialEq without having to type it once for NoteOn and once for Noteff ?或者是否有另一种方法可以通用地实现这个PartialEq而不必为NoteOn输入一次,为Noteff输入一次?

thank you谢谢你

Here is my best "attempt" at a possible way to do what i wanted, but in a different way following the remarks from @trentcl and @Shepmaster.这是我最好的“尝试”,以一种可能的方式做我想做的事,但以不同的方式遵循@trentcl 和@Shepmaster 的评论。

I used an Enum as mentioned by @trentctl to be able to switch between the different types, I keep the enum value within a common struct Event so I can easily wrap the different objects and add more code to the Event.我使用@trentctl 提到的 Enum 能够在不同类型之间切换,我将枚举值保留在一个公共结构事件中,以便我可以轻松地包装不同的对象并向事件添加更多代码。 Doing this also helps to make an easy Vec type.这样做也有助于制作一个简单的 Vec 类型。

Here i imagine that i only need the Enum, and not Event and an attribute with the enum, I am still learning the variant enum usage在这里,我想我只需要枚举,而不需要事件和枚举的属性,我仍在学习变体枚举的用法

I also had issues mentioned by @trentcl about the fact i did not own the Vec type, so i wrapped the Vec in a struct Sec instead of simply aliasing the type.我也遇到了@trentcl 提到的关于我不拥有 Vec 类型这一事实的问题,所以我将 Vec 包装在一个 struct Sec 中,而不是简单地将类型别名化。 This makes my implementation of PartialEq seperated from the type Vec (if i understand, but im not sure) => the reason i am troubled here is that I thought that using type A = B;这使得我的 PartialEq 实现与 Vec 类型分离(如果我理解,但我不确定)=> 我在这里感到困扰的原因是我认为使用type A = B; did create a new type, but the documentation does state it s aliasing (which could make send to why im not able to implement PartialEq for Vec) although in the end I imagine i may be very wrong on that too as the fact i created an artificial struct to just wrap 1 attribute also seems counter productive确实创建了一个新类型,但文档确实说明了它的别名(这可能会导致为什么我无法为 Vec 实现 PartialEq)尽管最后我想我在这方面也可能是非常错误的,因为我创建了一个仅包装 1 个属性的人工结构似乎也适得其反

=> So to conclude for now thank you everyone, I will keep working on this to see how it could be more efficient, but I guess I was simply using the wrong stuff for the context of Rust, I am not sure this is a good answer and would appreciate feedbacks or other suggestions . => 所以现在总结一下谢谢大家,我会继续努力,看看它如何更有效,但我想我只是在 Rust 的上下文中使用了错误的东西,我不确定这是一个好的回答并希望得到反馈或其他建议

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d67b7d993fa6b6285962ee58e9b215e5 https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d67b7d993fa6b6285962ee58e9b215e5

type Data = Vec<u8>;

#[derive(Debug)]
enum EventImpl{
    NoteOn(u8),
    NoteOff(u8)
}
#[derive(Debug)]
struct Event{
    data:Data,
    i:EventImpl
}

impl Event{
    fn new(data:Data)->Self{
        Event{
            i: match data[0]{
                0 => EventImpl::NoteOn(data[1]),
                1 => EventImpl::NoteOff(data[1]),
                _ => panic!("unk")
            },
            data:data
        }
    }

    fn data(&self)->&Data{
        &self.data
    }
}
#[derive(Debug)]
struct Seq{
    pub things:Vec<Event>
}

impl PartialEq for Seq{
    fn eq(&self,o:&Self)->bool{
    // i have to learn the iterator implementation    
        let mut r=o.things.len()==self.things.len();
        if ! r{
            return false;
        }
        for i in 0..o.things.len() {
            r = r && o.things[i]==self.things[i];
        }
        r
    }
}
impl PartialEq for Event{
    fn eq(&self,o:&Self)->bool{
    // i have to learn the iterator implementation    
        std::mem::discriminant(&self.i) == std::mem::discriminant(&o.i) && o.data()==self.data()
    }
}


fn main() {
    let mut s:Seq=Seq{things:vec![Event::new(vec![1,2,3])]};
    s.things.push(Event::new(vec![0,1,2]));
    let s2:Seq=Seq{things:vec![Event::new(vec![1,2,3]),Event::new(vec![0,1,2])]};

    println!("Hello, world! {:?} {:?}",s, s.things[1].data());
    println!("S1 == S2 ? {}",s==s2);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM