当前位置: 首页 > 知识库问答 >
问题:

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

岳曦
2023-03-14

编者按:此代码示例来自Rust 1.0之前的版本,并且在语法上是无效的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个答案

皇甫乐
2023-03-14

在trait对象的某些情况下,您希望基于通过trait暴露的某些属性对它们进行比较。您可以通过在trait类型本身上实现方法来实现这一点:

trait A {
    fn id(&self) -> i32;
}

impl PartialEq for dyn A + '_ {
    fn eq(&self, other: &Self) -> bool {
        self.id() == other.id()
    }
}

impl Eq for dyn A + '_ {}

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

这并不能直接解决希望委托回底层类型的PartialEq实现的原始情况,但您可以组合现有解决方案:

impl PartialEq for dyn A + '_ {
    fn eq(&self, other: &Self) -> bool {
        self.equals_a(other)
    }
}

另见:

  • 为什么我要在特性上实现方法,而不是作为特性的一部分?
宰鸿博
2023-03-14

在弗拉基米尔·马特维耶夫(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)
}
皇甫飞飙
2023-03-14

以下是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 { ... }
}

请注意如何实现的类型的其他更改,以反映类型ParatalEq

这就是问题所在。在trait对象中,实际类型被擦除,并且在运行时不可用。这意味着不可能从trait对象获得对具体类型的引用;特别是,您不能从

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

 类似资料:
  • 问题内容: 假设我有一个单元测试,想要比较两个复数对象是否相等。这些对象包含许多其他深层嵌套的对象。所有对象的类都有正确定义的方法。 这并不困难: 麻烦的是,如果对象不相等,那么您得到的只是一个失败,没有迹象表明对象图的哪一部分不匹配。调试它可能会很痛苦且令人沮丧。 我当前的方法是确保一切都实现了,然后像这样比较相等性: 由于像Eclipse这样的IDE具有一个特殊的可视化比较器,用于显示失败测试

  • 使用Jest测试深层嵌套属性是否存在的最佳方法是什么。尝试以我想要的特定对象为目标将导致未定义的错误,因为其父对象不存在: 我应该以某种方式将这些连接起来,这样我就可以首先测试对象的存在,然后测试内部对象的存在吗?相当于在if语句中做这样的事情 或者像这样在一个元素上进行多个测试时,是否应该有单独的测试? 我也尝试过: 这有点管用?更好,但是需要我在测试文件中声明这个非常大的对象。这种非常深入的比

  • 问题内容: 为什么下面的代码打印? 问题答案: 为什么下面的代码打印? 因为执行比较 浅 。由于数组从中继承其-method ,将对内部数组执行同一性比较,这将失败,因为和均未引用 相同的 数组。 如果更改为它将按预期打印。

  • 我需要检测一个球(椭圆形)和多个块(矩形)之间的碰撞。在游戏中表示块的类块中,我有以下代码来检测碰撞(其简短版本,仅用于演示示例): 碰撞不好,因为椭圆形,但一般来说,我想问是否有东西在java(摇摆)检测碰撞,我的意思是如果矩形没有完全显示在画布上,这意味着球重叠一个块坐标

  • 问题内容: 在类的equals()方法中,我使用私有实例HashMap变量进行相等性比较。但是,当比较两个对象的HashMap变量时,它们仍然显示相等。进一步的研究使我进入了链接:Link Here 。但是,它只是说HashMap1.equals(HashMap2)不起作用的原因是“显然,如果不编写自定义代码,就无法测试Java数组的相等性”。 我不明白这个原因。谁能指导我详细说明原因? 问题答案

  • 本文向大家介绍如何判断两个对象相等?相关面试题,主要包含被问及如何判断两个对象相等?时的应答技巧和注意事项,需要的朋友参考一下 提供另一种写法: 当然JSON.stringify(obj)==JSON.stringify(obj)执行速度是最快的