为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Git
婷婷同学_ 2019-11-20 10:27:23
编者注:此代码示例来自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}
查看完整描述

3 回答

?
DIEA

TA贡献1820条经验 获得超2个赞

这是特征的定义PartialEq:


pub trait PartialEq<Rhs = Self> 

where

    Rhs: ?Sized, 

{

    fn eq(&self, other: &Rhs) -> bool;


    fn ne(&self, other: &Rhs) -> bool { ... }

}

注意Self参数类型。这意味着eq()和ne()方法接受与实现程序相同类型的参数。例如:


impl PartialEq for i32 {

    fn eq(&self, other: &i32) -> bool { ... }

}


impl PartialEq for String {

    fn eq(&self, other: &String) -> bool { ... }

}

请注意如何实现other更改类型以反映该类型PartialEq。


这就是问题。在特征对象中,实际类型将被删除并且在运行时不可用。这意味着不可能从特征对象获得对具体类型的引用。特别是,你不能去&A到&T在你的榜样。


这意味着不可能Self在特征对象上调用接受或返回类型的方法。确实,这些方法总是需要一个具体的类型,但是如果您只有一个特征对象,那么就没有具体的类型,而且这种方法也无法以任何明智的方式起作用。


查看完整回答
反对 回复 2019-11-20
?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

在弗拉基米尔·马特维耶夫(Vladimir Matveev)的帮助下,我找到了一种方法,用于Any将我的特征转换为具体类型,并测试结果的相等性:


// `Any` allows us to do dynamic typecasting.

use std::any::Any;


trait A {

    // An &Any can be cast to a reference to a concrete type.

    fn as_any(&self) -> &dyn Any;


    // Perform the test.

    fn equals_a(&self, _: &dyn A) -> bool;

}


#[derive(Debug, PartialEq)]

enum T {

    Ta,

    Tb,

}


// Implement A for all 'static types implementing PartialEq.

impl<S: 'static + PartialEq> A for S {

    fn as_any(&self) -> &dyn Any {

        self

    }


    fn equals_a(&self, other: &dyn A) -> bool {

        // Do a type-safe casting. If the types are different,

        // return false, otherwise test the values for equality.

        other

            .as_any()

            .downcast_ref::<S>()

            .map_or(false, |a| self == a)

    }

}


fn main() {

    assert_eq!(T::Ta, T::Ta);

    assert_ne!(T::Ta, T::Tb);

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

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

}


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

    // It works!

    an_a.equals_a(another_a)

}


查看完整回答
反对 回复 2019-11-20
  • 3 回答
  • 0 关注
  • 534 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信