2016-01-22 42 views

回答

15

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> { 
    // .. 
} 
+1

感谢您的快速和详细的回复!通常我非常同意你使用枚举将我的值限制为标准套牌值。不过,就我而言,我一般使用“卡”一词,而不是纸牌,所以我需要一个未指定值的等级。 我是否正确理解我应该使用类型别名,如果我想要简单替换,以及如果我想要施加其他限制/逻辑,则使用新类型? –

+0

@ErikUggeldahl是的,这听起来正确。新类型允许额外的限制或逻辑,而别名​​就是这样,另一个名字就是同一个名字。 – Shepmaster

+2

@ErikUggeldahl它不仅限制了值。别名不提供额外的类型安全性,因为它不是...新类型,但同一类型的另一个名称。你能够计算一个'Rank/5'或将一个'Rank'传递给一个需要'u8'的函数吗?因为类型别名允许你这样做(因为'Rank' *是* u8')。你通常在Rust中使用类型别名是为了方便,当你有一个非常长和复杂的类型并且想要更简洁地引用它时(但别名*是*类型并且应该用来代替它到处) –

相关问题