2017-07-03 43 views
0

我知道如何使用像Java這樣的繼承語言或類似JavaScript的無類型語言來製作相關事物的列表,但我無法弄清楚如何在Rust中執行此操作。這將產生一個錯誤,因爲在編譯時Dereference中的數組大小未知。不帶繼承的不同事物的列表?

#[derive(PartialEq, Eq, PartialOrd, Ord)] 
struct Appearance<'a> { 
    identity: &'a u64, 
    role:  &'a str 
} 

struct Dereference<'a> { 
    set:  [&'a Appearance<'a>] 
} 

fn main() { 
    let r = "hair_color"; 
    let i1 = 42; 
    let i2 = 43; 
    let a1 = Appearance{identity: &i1, role: r}; 
    let a2 = Appearance{identity: &i2, role: r}; 
    let d1 = Dereference{set: [&a1]}; 
    let d2 = Dereference{set: [&a1, &a2]}; 
    let list: Vec<Dereference> = vec!(d1, d2); 
} 

然而,set構件在Dereference將陣列高達小尺寸。比方說少於32,最常見的是1或2,很少3,並且幾乎沒有那麼大。我可以創建32個結構體和32個列表,但爲了方便起見,我真的希望以更智能的方式來完成此操作。即使我必須創建32個結構,至少單個列表也會有很大的幫助。我需要這個同時成爲內存和性能高效。我如何在Rust中實現這一點?

+0

你需要'Dereference'結構嗎? [你可以直接使用切片](https://play.rust-lang.org/?gist=16de06c82ec2ddbe2f288386aa5336d8&version=stable&backtrace=0) – red75prime

+0

我相信我這樣做,因爲對Dereference的引用將被包含在另一個名爲Posit的結構體中,而我將需要一個從Dereference實例的查找表到引用該特定實例的Posit的所有實例。 –

+0

這不是問題。你可以使用'&[Appearance]'而不是'Derefenence <'a>'。但值得記住的是,Rust默認使用結構相等。如果兩個參考指向不同但相同的結構,則認爲它們相等。 – red75prime

回答

6

這不需要繼承;類型[&'a Appearance<'a>]是未分類的類型。它只能在指針後面引用,如&[&'a Appearance<'a>]

你可能想要的是Vec<&'a Appearance<'a>>。真的,Vec<Appearance>可能會更好,#[derive(Copy)]Appearance,因爲Appearance本身是一堆的參考文獻,並沒有太多的一點參考引用一堆。


雖然你的例子並不試圖使相關的事情的清單,(它只是使的Appearance的List),有兩種方法在魯斯特做到這一點。一種方法是使用枚舉,即您執行類似enum Things {Thing1(Type1), Thing2(Type2), ...}的操作,並存儲Vec<Things>。這樣可以避免額外的分配,但有點更多打字。或者,您可以使用特質對象,通過使用所需的所有方法定義特徵,針對相關類型實施特徵,並使用Vec<&TraitName>Vec<Box<TraitName>>

+0

這是你的建議使用枚舉的遊樂場:https://play.rust-lang.org/?gist=1af8376b839d04cc0108647a05d04a96&version=stable&backtrace=0 –

+0

事實證明,枚舉將由其最大的成員的大小,自從大多數數組將是一元或二元的,下面的解決方案似乎更好:https://play.rust-lang.org/?gist=0039bd821df7e7771496b09a34fec765&version=stable&backtrace=0 –

0

魯斯特數組是唯一有用的,當你知道它在編譯時的大小,例如:

struct 3DPoint { 
    position: [f32; 3], 
    // etc. 
} 

當你不知道在編譯時的大小,使用動態數組,所謂Vec

#[derive(PartialEq, Eq, PartialOrd, Ord)] 
struct Appearance<'a> { 
    identity: &'a u64, 
    role:  &'a str 
} 

struct Dereference<'a> { 
    set:  Vec<&'a Appearance<'a>> 
} 

fn main() { 
    let r = "hair_color"; 
    let i1 = 42; 
    let i2 = 43; 
    let a1 = Appearance{identity: &i1, role: r}; 
    let a2 = Appearance{identity: &i2, role: r}; 
    let d1 = Dereference{set: [&a1]}; 
    let d2 = Dereference{set: [&a1, &a2]}; 
    let list: Vec<Dereference> = vec!(d1, d2); 
} 

當你在Rust開發時,總是考慮堆棧。如果我很好地理解你的問題,你想堆積東西而不指定大小:這是不可能的。

+0

是的,我在想32個不同的結構體,每個使用數組的集合的大小都會使這些實例在棧上結束,而列表總是在堆上。在具有繼承性的語言中,我可以創建一個超類Dereference,然後實現32個不同的子類,同時仍然有一個基於超類的單個列表。這在Rust中是不可能的嗎? –

+0

對不起,我不明白這個問題...目前尚不可能(該功能即將推出),但即使可能,您也無法在不裝箱的情況下創建不同的「子類」(使用您的單詞)的矢量,即*將它們放入堆中。我會相應地更新我的答案,但現在我沒有時間。 – Boiethios