2016-01-22 14 views

risposta

15

Da The Rust Programming Language sezione intitolata `type` Aliases:

Il type parola chiave consente di dichiarare un alias di un altro tipo:

type Name = String; 

è possibile utilizzare questo tipo, come se fosse un vero e proprio tipo:

type Name = String; 
let x: Name = "Hello".to_string(); 

C'è altro che dovresti leggere, ma questo risponde alla domanda.


come un po 'editoriale, non credo che un tipo alias è una grande misura in un sacco di posti che la gente li utilizzano. Supponendo che il tuo tipo Rank rappresenti qualcosa da fare con un mazzo di carte, ti suggerirei uno enum o uno newtype. La ragione è che con un tipo di alias che si può fare qualcosa di simile:

let rank: Rank = 100; 

Che è senza senso per un mazzo di carte tipico. Un enum è un set limitato. Questo significa che non si può mai creare un invalido 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, 
      // ... 
     } 
    } 
} 

Un Newtype è solo un tipo di involucro. Non consuma spazio extra rispetto al tipo avvolto, fornisce solo un nuovo tipo effettivo che consente di implementare metodi che possono limitare a valori validi. E 'possibile creare valori non validi, ma solo entro il proprio codice, non tutto il codice del client:

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 
    } 
} 

tendo a usare gli alias di tipo come segnaposto veloci di tipi. Durante la scrittura gli esempi di cui sopra, ho scritto:

type Error =(); 

E tornato un Result<Rank, Error>, ma poi pensato che sarebbe stato fonte di confusione. :-)

L'altro caso che li uso è quello di accorciare un tipo più grande che non voglio nascondere. Ciò accade con tipi come iteratori o Result s, che è possibile see in the standard library. Qualcosa di simile:

type CardResult<T> = Result<T, Error>; 

fn foo() -> CardResult<String> { 
    // .. 
} 
+1

Grazie per la risposta rapida e dettagliata! Normalmente sarei molto d'accordo con te sull'uso delle enumerazioni per limitare i miei valori ai valori standard del mazzo. Tuttavia, nel mio caso uso genericamente il termine "carta", e non la carta da gioco, quindi ho bisogno di un rango di valore non specificato. Sto capendo correttamente che dovrei usare un alias di tipo se voglio una semplice sostituzione, e un newtype se mi piacerebbe imporre ulteriori restrizioni/logica? –

+0

@ErikUggeldahl sì, sembra corretto. Un newtype consente ulteriori restrizioni o logica, mentre un alias è proprio questo, un altro nome per la stessa cosa. – Shepmaster

+2

@ErikUggeldahl non solo limita i valori. Un alias non fornisce sicurezza di tipo aggiuntivo perché non è un ...nuovo tipo, ma un altro nome per lo stesso tipo. Ha senso per te essere in grado di calcolare un 'Rank/5' o passare un' Rank' a una funzione che prende un 'u8'? Perché un alias di tipo ti permette di farlo (dato che 'Rank' * è * a 'u8'). Quello che in genere usi alias di tipo Rust è per comodità quando hai un tipo molto lungo e complesso e vuoi farvi riferimento in modo più conciso (ma l'alias * è * il tipo e dovrebbe essere usato al posto di esso ovunque) –