2015-09-13 18 views
7

Esiste un tipo di cancellazione di generici in Rust (come in Java) o no? Non riesco a trovare una risposta definitiva.Rust cancella i tipi generici o no?

+1

Potrebbe essere necessario definire cosa intendi per "cancellazione tipo" per ottenere il risposte più utili – Shepmaster

+1

@Shepmaster La cancellazione dei caratteri per i generici è [un concetto ben definito] (https://docs.oracle.com/javase/tutorial/java/generics/erasure.html) in linguaggio JVM come Java e Scala, ma non si verifica con i generici in qualsiasi altra lingua che conosco.Le persone che conoscono il moderno Java sapranno cosa significa "cancellazione di tipo". – Iceberg

risposta

10

Quando si utilizza una funzione generica o un tipo generico, il compilatore genera un'istanza separata per ciascun set distinto di parametri di tipo (credo che i parametri di durata siano ignorati, in quanto non hanno alcuna influenza sul codice generato). Questo processo si chiama monomorfizzazione. Ad esempio, Vec<i32> e Vec<String> sono diversi tipi, e quindi Vec<i32>::len() e Vec<String>::len() sono diverse funzioni. Questo è necessario, perché Vec<i32> e Vec<String> hanno diversi layout di memoria e quindi hanno bisogno di un codice macchina diverso! Pertanto, no, non è presente alcun tipo di cancellazione.

Se usiamo Any::get_type_id() (instabile per ora, quindi deve essere compilato con un compilatore notturno), come il seguente esempio:

#![feature(get_type_id)] 

use std::any::Any; 

fn main() { 
    let v1: Vec<i32> = Vec::new(); 
    let v2: Vec<String> = Vec::new(); 

    let a1 = &v1 as &Any; 
    let a2 = &v2 as &Any; 

    println!("{:?}", a1.get_type_id()); 
    println!("{:?}", a2.get_type_id()); 
} 

otteniamo ID di tipo diverso per due istanze di Vec. Questo supporta il fatto che Vec<i32> e Vec<String> sono tipi distinti.

Tuttavia, le capacità di riflessione in Rust sono limitate; Any è praticamente tutto quello che abbiamo per ora. Non è possibile ottenere ulteriori informazioni sul tipo di un valore di runtime, come il suo nome oi suoi membri. Per poter lavorare con Any, devi eseguirlo (usando Any::downcast_ref() o Any::downcast_mut() per un tipo noto al momento della compilazione.

+0

Sembra che io e te non siamo d'accordo^_ ^. Forse c'è una sfumatura nella domanda che sto mancante ... – Shepmaster

+3

@Shepmaster: in Java, la cancellazione di tipo è rilevante perché è come se i parametri del tipo non fossero mai stati lì. Ad esempio, è possibile memorizzare un 'String' in un 'ArrayList ', perché non esiste una cosa come 'ArrayList ' in fase di esecuzione; è solo un 'ArrayList'. L'unico vantaggio nell'usare i generici in Java è che il compilatore inserirà dei cast per te dove è sicuro, mentre senza i generici, dovresti digitare tu stesso i cast (e potresti sbagliarli). –

+0

Che dire 'Vec >'? – aochagavia