我正在用Rust 1.6编写我的现有代码,我发现在源语言中用typedef标记一个类型非常方便.例如,在我的纸牌游戏中,我在F#中有一个等级值定义为:
type Rank = uint8
我正在用Rust 1.6编写我的现有代码,我发现在源语言中用typedef标记一个类型非常方便.例如,在我的纸牌游戏中,我在F#中有一个等级值定义为:
type Rank = uint8
来自标题为Creating Type Synonyms with Type Aliases的The Rust Programming Language节:
Rust提供了声明一个type alias来为现有类型命名的能力.为此,我们使用type
关键字.例如,我们可以这样创建别名Kilometers
到i32
:
type Kilometers = i32;
现在,别名Kilometers
是i32
的同义词;[...], Kilometers
不是一个单独的新类型.类型为i32
的值将与类型为i32
的值相同:
type Kilometers = i32;
let x: i32 = 5;
let y: Kilometers = 5;
println!("x + y = {}", x + y);
还有很多你应该读的,但这回答了问题.
作为一篇社论,我不认为类型别名非常适合人们使用它们的很多地方.假设你的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, ()> {
use Rank::*;
let r = match v {
1 => One,
2 => Two,
// ...
_ => return Err(()),
};
Ok(r)
}
fn value(&self) -> u8 {
use Rank::*;
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
s之类的类型上,可以使用see in the standard library.比如:
type CardResult<T> = Result<T, Error>;
fn foo() -> CardResult<String> {
// ..
}