在Rust中使用具有特征的Any

Jac*_*und 7 traits rust

我正在尝试PartialEq在Rust中实现具有子类型的特征,以便我可以将它们作为盒装指针添加到容器中,然后比较它们.

这是我缩小的实现:

use std::any::Any;

trait Foo: Any {}

struct Bar {}

impl Foo for Bar {}

struct Baz {}

impl Foo for Baz {}

impl PartialEq for Foo {
    fn eq(&self, other: &Foo) -> bool {
        let me = self as &Any;
        let you = other as &Any;
        if me.is::<Bar>() && you.is::<Bar>() {
            true
        } else if me.is::<Baz>() && you.is::<Baz>() {
            true
        } else {
            false
        }
    }
}

fn main() {
    let bar: Bar = Bar {};
    let baz: Baz = Baz {};
    let foo1: &Foo = &bar;
    let foo2: &Foo = &baz;
    println!("{:?}", foo1 == foo2);
}
Run Code Online (Sandbox Code Playgroud)

Rust Playground中的代码示例.

当我构建这个时,我得到:

rustc 1.17.0-nightly (0648517fa 2017-02-03)
error: non-scalar cast: `&Foo + 'static` as `&std::any::Any + 'static`
  --> <anon>:15:18
   |
15 |         let me = self as &Any;
   |                  ^^^^^^^^^^^^

error: non-scalar cast: `&Foo + 'static` as `&std::any::Any + 'static`
  --> <anon>:16:19
   |
16 |         let you = other as &Any;
   |                   ^^^^^^^^^^^^^

error: aborting due to 2 previous errors
Run Code Online (Sandbox Code Playgroud)

这令人困惑.我在这里做错了什么想法?

编辑:我不相信这是一个副本为什么不支持特技对象向上转换?因为我要做的就是贬低使用Any,而不是向上.

进一步编辑:是的,这是一个重复 - 对不起,我正在考虑我想要做什么(向下转向BarBaz类型),而不是我是如何做到的(向上转发Any).然而,话虽这么说,我想我仍然不明白为什么任何一个例子,他们这样做:let value_any = value as &Any;工作,我的没有.话虽如此,Joshua Entrekin确实给出了一个很好的答案.

最后编辑一个,没关系,这是因为我正在向上倾斜一个特征而不是一个类型 - Doh!.感谢大家!

小智 8

这是为什么Rust不支持特征对象向上转换的副本?因为你是从试图上溯造型FooAny.如果您在其上添加as_any方法Foo并在其上实现,则可以使此代码起作用:

use std::any::Any;

trait Foo: Any {
    fn as_any(&self) -> &Any;
}

impl<T: Any> Foo for T {
    fn as_any(&self) -> &Any {
        self
    }
}

struct Bar {}

struct Baz {}

impl PartialEq for Foo {
    fn eq(&self, other: &Foo) -> bool {
        let me = self.as_any();
        let you = other.as_any();
        if me.is::<Bar>() && you.is::<Bar>() {
            true
        } else if me.is::<Baz>() && you.is::<Baz>() {
            true
        } else {
            false
        }
    }
}

fn main() {
    let bar: Bar = Bar {};
    let baz: Baz = Baz {};
    let foo1: &Foo = &bar;
    let foo2: &Foo = &baz;
    println!("{:?}", foo1 == foo2);
}
Run Code Online (Sandbox Code Playgroud)

我在游乐场里展示它.