2015-08-31 16 views

risposta

22

self se utilizzato come argomento del primo metodo, è una stenografia per self: Self. Esistono anche &self, che equivale a self: &Self e &mut self, che equivale a self: &mut Self.

Self in argomenti del metodo è zucchero sintattico per il tipo di ricezione del metodo (cioè il tipo avente impl questo metodo è in). Ciò consente anche tipi generici senza troppe ripetizioni.

40

Self è il tipo dell'oggetto corrente. Può apparire sia in un trait o un impl, ma appare più spesso in trait dove è uno stand-in per qualsiasi tipo finirà per l'attuazione del trait (che è sconosciuto al momento di definire la trait):

trait Clone { 
    fn clone(&self) -> Self; 
} 

Se io quindi implementare Clone:

impl Clone for MyType { 
    // I can use either the concrete type (known here) 
    fn clone(&self) -> MyType; 

    // Or I can use Self again, it's shorter after all! 
    fn clone(&self) -> Self; 
} 

potrei anche usarlo in un normale impl se io sono pigro (è più corta!):

impl MySuperLongType { 
    fn new(a: u32) -> Self { ... } 
} 

self è il nome utilizzato in un trait o un impl per il primo argomento di un metodo. Utilizzando un altro nome è possibile, tuttavia v'è una differenza notevole:

  • se si utilizza self, la funzione introdotta è un metodo
  • se utilizzando qualsiasi altro nome, la funzione introdotta è una funzione associata

In Rust, non esiste un argomento implicito this passato ai metodi di un tipo: è necessario passare esplicitamente "l'oggetto corrente" come parametro del metodo. Questo si tradurrebbe in:

impl MyType { 
    fn doit(this: &MyType, a: u32) { ... } 
} 

Come abbiamo visto, come una forma più breve questo potrebbe anche essere (ancora verbose):

impl MyType { 
    fn doit(this: &Self, a: u32) { ... } 
} 

che è in realtà ciò che &self si riduce a sotto le coperte.

impl MyType { 
    fn doit(&self, a: u32) { ... } 
} 

Quindi, la tabella di corrispondenza:

self => self: Self 
&self => self: &Self 
&mut self => self: &mut Self 

Il modo per richiamare le funzioni cambiano, tuttavia:

impl MyType { 
    fn doit(&self, a: u32) { 
     // ... 
    } 
    fn another(this: &Self, a: u32) { 
     // ... 
    } 
} 

fn main() { 
    let m = MyType; 

    // Both can be used as an associated function 
    MyType::doit(&m, 1); 
    MyType::another(&m, 2); 

    // But only `doit` can be used in method position 
    m.doit(3);  // OK: `m` is automatically borrowed 
    m.another(4); // ERROR: no method named `another` 
} 
+0

** Può apparire in un tratto o in un impl ** - non può apparire in "struct"? –

+0

@jawanam: Personalmente ottengo * errore: uso di 'Self' al di fuori di impl o trait * se lo provo. Forse la restrizione è stata revocata in una versione più recente? –

+1

No, al momento non è possibile (a partire dalla notte 2015-09-01). Le strutture autoreferenziali sono piuttosto rare, quindi aggiungere l'autoassistenza in questo caso è stato considerato a bassa priorità. – llogiq