如何测试特征对象之间的相等性?

编者注:此代码示例来自1.0之前的Rust版本,在语法上不是有效的Rust 1.0代码。此代码的更新版本会产生不同的错误,但是答案仍然包含有价值的信息。


在以下情况下,我们似乎无法测试是否相等。为什么是这样?有解决方法吗?(我正在使用Rust 0.11)。


trait A: PartialEq {}


#[deriving(PartialEq)]

enum T {Ta, Tb}


impl A for T {}


fn main() {

  assert!(Ta == Ta);

  assert!(Ta != Tb);

  assert!(some_fn(&Ta, &Ta));

  assert!(!some_fn(&Ta, &Tb));

}


fn some_fn(an_a: &A, another_a: &A) -> bool {

    an_a == another_a

// ERROR ^~~~~~~~~~~~ binary operation `==` cannot be applied to type `&A`

}


fn another_fn(an_a: &A + PartialEq, another_a: &A + PartialEq) -> bool {

               // ERROR: ^~~~~~~~~ only the builtin traits can be used as closure or object bounds

    an_a == another_a

}


婷婷同学_
浏览 535回答 3
3回答

DIEA

这是特征的定义PartialEq:pub trait PartialEq<Rhs = Self>&nbsp;where&nbsp; &nbsp; Rhs: ?Sized,&nbsp;{&nbsp; &nbsp; fn eq(&self, other: &Rhs) -> bool;&nbsp; &nbsp; fn ne(&self, other: &Rhs) -> bool { ... }}注意Self参数类型。这意味着eq()和ne()方法接受与实现程序相同类型的参数。例如:impl PartialEq for i32 {&nbsp; &nbsp; fn eq(&self, other: &i32) -> bool { ... }}impl PartialEq for String {&nbsp; &nbsp; fn eq(&self, other: &String) -> bool { ... }}请注意如何实现other更改类型以反映该类型PartialEq。这就是问题。在特征对象中,实际类型将被删除并且在运行时不可用。这意味着不可能从特征对象获得对具体类型的引用。特别是,你不能去&A到&T在你的榜样。这意味着不可能Self在特征对象上调用接受或返回类型的方法。确实,这些方法总是需要一个具体的类型,但是如果您只有一个特征对象,那么就没有具体的类型,而且这种方法也无法以任何明智的方式起作用。

小怪兽爱吃肉

在弗拉基米尔·马特维耶夫(Vladimir Matveev)的帮助下,我找到了一种方法,用于Any将我的特征转换为具体类型,并测试结果的相等性:// `Any` allows us to do dynamic typecasting.use std::any::Any;trait A {&nbsp; &nbsp; // An &Any can be cast to a reference to a concrete type.&nbsp; &nbsp; fn as_any(&self) -> &dyn Any;&nbsp; &nbsp; // Perform the test.&nbsp; &nbsp; fn equals_a(&self, _: &dyn A) -> bool;}#[derive(Debug, PartialEq)]enum T {&nbsp; &nbsp; Ta,&nbsp; &nbsp; Tb,}// Implement A for all 'static types implementing PartialEq.impl<S: 'static + PartialEq> A for S {&nbsp; &nbsp; fn as_any(&self) -> &dyn Any {&nbsp; &nbsp; &nbsp; &nbsp; self&nbsp; &nbsp; }&nbsp; &nbsp; fn equals_a(&self, other: &dyn A) -> bool {&nbsp; &nbsp; &nbsp; &nbsp; // Do a type-safe casting. If the types are different,&nbsp; &nbsp; &nbsp; &nbsp; // return false, otherwise test the values for equality.&nbsp; &nbsp; &nbsp; &nbsp; other&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .as_any()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .downcast_ref::<S>()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map_or(false, |a| self == a)&nbsp; &nbsp; }}fn main() {&nbsp; &nbsp; assert_eq!(T::Ta, T::Ta);&nbsp; &nbsp; assert_ne!(T::Ta, T::Tb);&nbsp; &nbsp; assert!(some_fn(&T::Ta, &T::Ta));&nbsp; &nbsp; assert!(!some_fn(&T::Ta, &T::Tb));}fn some_fn(an_a: &dyn A, another_a: &dyn A) -> bool {&nbsp; &nbsp; // It works!&nbsp; &nbsp; an_a.equals_a(another_a)}
打开App,查看更多内容
随时随地看视频慕课网APP