Funções e Métodos Associados
Algumas funções são conectadas à um topo específico. Existem em duas formas: funções associadas, e métodos. As funções associadas são funções que são definidas geralmente sobre um tipo, enquanto os métodos são funções associadas que são chamados sobre uma instância específica dum tipo:
struct Point {x: f64,y: f64,}// Bloco de implementação, todas funções associadas do `Point`// e os métodos são colocados neste blocoimpl Point {// Isto é uma "função associada" pois esta função está associada à// um tipo específico, que é, `Point`.//// Funções associadas não precisam ser chamadas com uma instância.// Estas funções são geralmente usadas como construtoras.fn origin() -> Point {Point { x: 0.0, y: 0.0 }}// Uma outra função associada, recebendo dois argumentos:fn new(x: f64, y: f64) -> Point {Point { x: x, y: y }}}struct Rectangle {p1: Point,p2: Point,}impl Rectangle {// Isto é um método// `&self` é açúcar sintático para `self: &Self`,// aonde `Self` é o tipo do objeto chamador.// Neste caso `Self` = `Rectangle`fn area(&self) -> f64 {// `self` dá acesso aos campos da estrutura através do// operador pontolet Point { x: x1, y: y1 } = self.p1;let Point { x: x2, y: y2 } = self.p2;// `abs` é um método de `f64` que retorna o// valor absoluto do chamador((x1 - x2) * (y1 - y2)).abs()}fn perimeter(&self) -> f64 {let Point { x: x1, y: y1 } = self.p1;let Point { x: x2, y: y2 } = self.p2;2.0 * ((x1 - x2).abs() + (y1 - y2).abs())}// Este método exige que objeto chamador seja mutável.// `&mut self` é açúcar para `self: &mut Self`fn translate(&mut self, x: f64, y: f64) {self.p1.x += x;self.p2.x += x;self.p1.y += y;self.p2.y += y;}}// `Pair` possui os recursos: dois amontoados alocados de inteirosstruct Pair(Box<i32>, Box<i32>);impl Pair {// Este método "consome" os recursos do objeto chamador// `self` é açúcar para `self: Self`fn destroy(self) {// Desestruturar `self`let Pair(first, second) = self;println!("Destroying Pair({}, {})", first, second);// `first` e `second` saem do âmbito e são liberados}}fn main() {let rectangle = Rectangle {// As funções associadas são chamadas usando dois-pontos duplosp1: Point::origin(),p2: Point::new(3.0, 4.0),};// Os métodos são chamados usando o operador ponto// Nota que o primeiro argumento `&self` é implicitamente passado, isto é,// `rectangle.perimeter()` === `Rectangle::perimeter(&rectangle)`println!("Rectangle perimeter: {}", rectangle.perimeter());println!("Rectangle area: {}", rectangle.area());let mut square = Rectangle {p1: Point::origin(),p2: Point::new(1.0, 1.0),};// Error! `rectangle` é imutável, mas este método exige um objeto mutável//rectangle.translate(1.0, 0.0);// TODO ^ Tente desfazer o comentário desta linha// Okay! Os objetos mutáveis podem chamar métodos mutáveissquare.translate(1.0, 1.0);let pair = Pair(Box::new(1), Box::new(2));pair.destroy();// Error! A chama de `destroy` anterior "consumiu" `pair`//pair.destroy();// TODO ^ Tente desfazer o comentário desta linha}