【问题标题】:Using Any with traits in Rust [duplicate]在 Rust 中使用带有特征的 Any [重复]
【发布时间】:2017-02-05 19:41:11
【问题描述】:

我正在尝试在 Rust 中为具有子类型的 trait 实现 PartialEq,以便我可以将它们作为装箱指针添加到容器中,然后再进行比较。

这是我按比例缩小的实现:

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);
}

Code example in 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

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

编辑:我不相信这是Why doesn't Rust support trait object upcasting? 的重复,因为我正在尝试使用Any 进行向下转换,而不是向上转换。

进一步编辑:是的,这是重复的 - 抱歉,我在考虑我想要做什么(向下转换为 BarBaz 类型)而不是我的本来面目这样做(向上转换为Any)。但是,话虽如此,我想我仍然不明白为什么Any example,他们这样做:let value_any = value as &amp;Any; 有效,而我的却没有。话虽如此,Joshua Entrekin 确实给出了很好的答案。

最终编辑 别介意,这是因为我正在向上转换一个特征而不是一个类型 - Doh!。谢谢大家!

【问题讨论】:

  • 我对这门语言太陌生了,无法告诉你所有的选择,但它看起来有点像你在尝试做 OO 风格的子类型。您是否尝试过使用某种枚举?
  • @JustinBlank 试过了,但是没有地方可以放 num AFAICT - 你不能给特征添加枚举,如果我做一个全局枚举,感觉很笨拙。 Any 的文档暗示,如果您的类型是 Any,您应该能够进行我正在做的那种转换 - 因此我的问题。
  • 您的编辑对我来说没有意义,我认为存在术语差异。您正在尝试将&amp;Foo 转换为&amp;Any在层次结构中向上。那是向上的。你为什么说你想低调? @JoshuaEntrekin also provides an example 这似乎有效。
  • @Shepmaster 抱歉,我评论了他的回复,但没有更新我的帖子。见上文。

标签: rust traits


【解决方案1】:

这是Why doesn't Rust support trait object upcasting? 的副本,因为您正尝试从Foo 向上转换为Any。如果将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);
}

我在Playground 中显示它。

【讨论】:

  • 非常感谢您做正确的事并指出重复。我希望你在rust 附近闲逛并帮助识别更多的骗子,也许也有机会回答一些非重复的问题! ^_^
  • 没有显式 dyn 的特征对象是 Rust 2021 中的一个硬错误。因此这里更新了 Playground
猜你喜欢
  • 2020-12-19
  • 1970-01-01
  • 2016-10-05
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2021-01-01
  • 1970-01-01
  • 2019-12-27
相关资源
最近更新 更多