我正在重寫Rust 1.6中的現有代碼,並且我發現在源語言中通過typedef標記類型非常方便。舉例來說,在我的紙牌遊戲,我已經定義了F#中排名值:Rust是否具有與F#typedefs相同的習慣用法?
type Rank = uint8
我正在重寫Rust 1.6中的現有代碼,並且我發現在源語言中通過typedef標記類型非常方便。舉例來說,在我的紙牌遊戲,我已經定義了F#中排名值:Rust是否具有與F#typedefs相同的習慣用法?
type Rank = uint8
從The Rust Programming Language標題爲`type` Aliases:
的
type
關鍵字可以聲明另一個類型的別名:type Name = String;
,就好像它是一個真正的類型,你可以使用這個類型:
type Name = String; let x: Name = "Hello".to_string();
還有更多的你應該閱讀,但這回答了這個問題。
作爲一種編輯方式,我不認爲類型別名很適合人們使用它們的很多地方。假設你的Rank
類型代表了一副撲克牌,我建議你要麼是enum
要麼是newtype。原因在於,對於類型別名,您可以這樣做:
let rank: Rank = 100;
這對於典型的一副牌是無意義的。枚舉是一個受限制的集合。這意味着你不能創建一個無效Rank
:
enum Rank {
One, Two, Three, Four, Five,
Six, Seven, Eight, Nine, Ten,
Jack, Queen, King, Ace,
}
impl Rank {
fn from_value(v: u8) -> Result<Rank,()> {
let r = match v {
1 => One,
2 => Two,
// ...
_ => return Err(()),
};
Ok(r)
}
fn value(&self) -> u8 {
match *self {
One => 1,
Two => 2,
// ...
}
}
}
一個NEWTYPE只是一個包裝類型。與包裝類型相比,它不佔用額外的空間,它只是提供了一種實際的新類型,可讓您實現可限制爲有效值的方法。它可以創建無效值,但僅限於你自己的代碼,不是所有的客戶端代碼:
struct Rank(u8);
impl Rank {
fn from_value(v: u8) -> Result<Rank,()> {
if v >= 1 && v <= 14 {
Ok(Rank(v))
} else {
Err(())
}
}
fn value(&self) -> u8 {
self.0
}
}
我傾向於使用類型別名爲類型的快速佔位符。在寫上面的例子,其實我寫的:
type Error =();
,並返回一個Result<Rank, Error>
,但後來認爲這將是混亂的。 :-)
我使用它們的另一種情況是縮短我不想隱藏的較大類型。這種情況發生在類似迭代器或Result
的情況下,您可以使用see in the standard library。例如:
type CardResult<T> = Result<T, Error>;
fn foo() -> CardResult<String> {
// ..
}
感謝您的快速和詳細的回覆!通常我非常同意你使用枚舉將我的值限制爲標準套牌值。不過,就我而言,我一般使用「卡」一詞,而不是紙牌,所以我需要一個未指定值的等級。 我是否正確理解我應該使用類型別名,如果我想要簡單替換,以及如果我想要施加其他限制/邏輯,則使用新類型? –
@ErikUggeldahl是的,這聽起來正確。新類型允許額外的限制或邏輯,而別名就是這樣,另一個名字就是同一個名字。 – Shepmaster
@ErikUggeldahl它不僅限制了值。別名不提供額外的類型安全性,因爲它不是...新類型,但同一類型的另一個名稱。你能夠計算一個'Rank/5'或將一個'Rank'傳遞給一個需要'u8'的函數嗎?因爲類型別名允許你這樣做(因爲'Rank' *是* u8')。你通常在Rust中使用類型別名是爲了方便,當你有一個非常長和複雜的類型並且想要更簡潔地引用它時(但別名*是*類型並且應該用來代替它到處) –