2015-01-31 16 views
6

a Rust 1.0.0-notte, questo codice funziona bene:Perché i newtypes non usano i tratti dal tipo interno?

fn main() { 
    let x = 10f64; 
    let y = 20f64; 
    let z = x + y; 
    println!("z = {}", z); 
} 

Ma se provo ad usare un newtype (secondo il rust book):

struct Metres(f64); 

fn main() { 
    let x = Metres(10f64); 
    let y = Metres(20f64); 
    let z = x + y; 
    println!("z = {}", z); 
} 

ottengo questo errore di compilazione:

test.rs:6:13: 6:18 error: binary operation `+` cannot be applied to type `Metres` 
test.rs:6  let z = x + y; 
         ^~~~~ 
error: aborting due to previous error 

Dal Metres è fondamentalmente un f64, perché il compilatore non può utilizzare lo stesso + operatore e creare un nuovo oggetto Metres per z?

Come posso utilizzare newtypes se non riesco a fare cose semplici come l'aggiunta e così via? In che modo sono "molto utili" (come li chiama il libro)?

(C'è un old question su questo, ma la ruggine cambia molto, quindi sto reasking)

risposta

9

La ragione newtypes funzionano in questo modo è in genere perché si vuole per evitare i tratti definiti sulla tipo sottostante Ad esempio, è possibile avere Metres e Feet che entrambi aggiungono ma definiscono l'aggiunta di Metres e Feet per eseguire la conversione di unità, che non fornisce l'aggiunta semplice f64.

Naturalmente, a volte si desidera l'implementazione del tratto sottostante. Attualmente, dovreste scrivere un involucro implementazione da soli, ma c'è un RFC per la capacità di generare automaticamente questi: https://github.com/rust-lang/rfcs/issues/479

+0

Questo in realtà ha molto senso. È un peccato che non ci sia un modo più breve per ricavare le cose. – Rory

5

Come accennato da Scott Olson, è in realtà di volontariato che newtypes non "degenerata" nella loro solo attributo. Sono qui per introdurre un nuovo tipo, dopo tutto.

Se quello che cercate è un sinonimo, che è leggermente diverso, quindi è possibile utilizzare un tipo alias invece:

type Metres = f64; 

Tuttavia, è poi perde i benefici di un nuovo tipo:

type Grams = f64; 

fn main() { 
    let m = 10 as Metres; 
    let g = 5 as Grams; 
    println!("{}", m + g); // prints 15, see http://is.gd/IdYOEg 
}