为实现特征的所有类型实现特征
Posted
技术标签:
【中文标题】为实现特征的所有类型实现特征【英文标题】:Implement a trait for all types implementing a trait 【发布时间】:2019-12-08 00:50:14 【问题描述】:我有这个问题:
多个结构实现一个特征Event
都可以用同样的方式实现PartialEq
trait
我考虑过写这个(短版)
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
编译失败:
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
这里有什么问题?
还是有另一种方法可以通用地实现这个PartialEq
,而不必为NoteOn
输入一次,为Noteff
输入一次?
谢谢
【问题讨论】:
看来I implemented a trait for another trait but cannot call methods from both traits 的答案可能会回答您的问题。如果没有,请edit您的问题来解释差异。否则,我们可以将此问题标记为已回答。 对您的失败进行更多猜测,您的问题可能会得到How is there a conflicting implementation ofFrom
when using a generic type?的答案。如果没有,请edit您的问题来解释差异。否则,我们可以将此问题标记为已回答。
或许您可以解释一下您对编译器帮助信息的不理解之处?
@Shepmaster 感谢您的 cmets,我制作了一个游乐场示例和可编译示例(无需板条箱)。问题是冲突,尽管错误消息:T must be used in Local type 对我来说意义不大,因为 T 用作本地类型。再次感谢
目前,这是How do I implement a trait I don't own for a type I don't own? 的骗子(回答:你不知道,但有一些变通方法)。更广泛地说,我认为您的问题可以通过How do I make many different structs that all implement the same trait comparable to each other? 和How to test for equality between trait objects? 中的一个或两个来解决(请务必阅读所有答案)。
【参考方案1】:
这是我最好的“尝试”,以一种可能的方式来做我想做的事,但在@trentcl 和@Shepmaster 的评论之后以不同的方式。
我使用@trentctl 提到的枚举来在不同类型之间切换, 我将枚举值保存在一个公共结构事件中,这样我就可以轻松地包装不同的对象并向事件添加更多代码。 这样做也有助于制作简单的 Vec 类型。
在这里我想我只需要枚举,而不是事件和带有枚举的属性,我仍在学习变体枚举的用法
我还遇到了@trentcl 提到的关于我不拥有 Vec 类型这一事实的问题,因此我将 Vec 包装在 struct Sec 中,而不是简单地为该类型设置别名。
这使我的 PartialEq 实现与 Vec 类型分离(如果我理解,但我不确定)
=> 我在这里感到困扰的原因是我认为使用type A = B;
did 创建了一个新类型,但文档确实说明它是别名(这可能会导致我无法为 Vec 实现 PartialEq)
虽然最后我想我可能也错了,因为我创建了一个人工结构来仅包装 1 个属性似乎也适得其反
=> 所以现在要结束了,谢谢大家,我会继续努力,看看它如何更有效,但我想我只是在 Rust 的上下文中使用了错误的东西,我是不确定这是一个好的答案,并希望得到反馈或其他建议。
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=Seqthings:vec![Event::new(vec![1,2,3])];
s.things.push(Event::new(vec![0,1,2]));
let s2:Seq=Seqthings: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);
【讨论】:
以上是关于为实现特征的所有类型实现特征的主要内容,如果未能解决你的问题,请参考以下文章