Exemplo

#[derive(Debug)]
struct Race {
    name: String,
    laps: Vec<i32>,
}

impl Race {
    fn new(name: &str) -> Race {  // Sem receptor, método estático
        Race { name: String::from(name), laps: Vec::new() }
    }

    fn add_lap(&mut self, lap: i32) {  // Empréstimo único com acesso de leitura e escrita em self
        self.laps.push(lap);
    }

    fn print_laps(&self) {  // Empréstimo compartilhado com acesso apenas de leitura em self
        println!("Registrou {} voltas para {}:", self.laps.len(), self.name);
        for (idx, lap) in self.laps.iter().enumerate() {
            println!("Volta {idx}: {lap} seg");
        }
    }

    fn finish(self) {  // Propriedade exclusiva de self
        let total = self.laps.iter().sum::<i32>();
        println!("Corrida {} foi encerrada, tempo de voltas total: {}", self.name, total);
    }
}

fn main() {
    let mut race = Race::new("Monaco Grand Prix");
    race.add_lap(70);
    race.add_lap(68);
    race.print_laps();
    race.add_lap(71);
    race.print_laps();
    race.finish();
    // race.add_lap(42);
}

Pontos Chave:

  • Todos os quatro métodos aqui usam um receptor de método diferente.
    • Você pode apontar como isso muda o que a função pode fazer com os valores das variáveis e se/como ela pode ser usada novamente na main.
    • Você pode mostrar o erro que aparece ao tentar chamar encerrar duas vezes.
  • Observe que, embora os receptores do método sejam diferentes, as funções não estáticas são chamadas da mesma maneira no corpo principal. Rust permite referenciar e desreferenciar automaticamente ao chamar métodos. Rust adiciona automaticamente &, *, muts para que esse objeto corresponda à assinatura do método.
  • Você pode apontar que imprimir_voltas está usando um vetor e iterando sobre ele. Descreveremos os vetores com mais detalhes à tarde.