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 bloco
impl 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 ponto
let 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 inteiros
struct 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 duplos
p1: 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áveis
square.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
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX