2017-02-05 78 views
4

我試圖在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); 
} 

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 &Any;作品,我的地方沒有。這就是說,Joshua Entrekin確實給出了很好的答案。

Final編輯一個,沒關係,這是因爲我是一個特性,而不是一個類型 - Doh!。感謝大家!

+0

我對這個語言太陌生了,告訴你所有的選擇,但它看起來有點像你正在嘗試做OO風格的子類型。你有沒有嘗試過使用某種類型的枚舉? –

+1

@JustinBlank試過了,但沒有地方可以放置AFAICT - 你不能添加一個枚舉到一個特性,如果我創建一個全局枚舉,它感覺非常kludgey。 Any的文檔暗示如果你的類型是Any,你應該能夠做我正在做的那種投射 - 因此我的問題。 –

+0

你的編輯對我來說沒有意義,我認爲這裏有術語上的差異。您試圖將'&Foo'轉換爲'&Any',*在層次結構中向上*。這是倒戈。你爲什麼說你試圖沮喪? [@JoshuaEntrekin也提供了一個例子](https://play.rust-lang.org/?gist=3aae5b8349e3420497f3aa24f9e8ea7b&version=nightly&backtrace=0)似乎有效。 – Shepmaster

回答

3

這是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

+0

太棒了!謝謝! –

+0

非常感謝你做正確的事情並指出重複。我希望你在[標籤:rust]附近閒逛,並幫助識別更多的模糊,也許有機會回答一些不重複的東西!^_ ^ – Shepmaster

相關問題