연관 함수와 메서드
일부 함수는 특정 타입과 연결되어 있습니다. 이들은 연관 함수와 메서드라는 두 가지 형태로 제공됩니다. 연관 함수는 일반적으로 타입 상에 정의된 함수인 반면, 메서드는 특정 타입의 인스턴스에서 호출되는 연관 함수입니다.
struct Point {
x: f64,
y: f64,
}
// 구현(Implementation) 블록으로, 모든 `Point` 연관 함수와 메서드가 여기에 들어갑니다.
impl Point {
// 이것은 이 함수가 특정 타입인 Point와 연관되어 있기 때문에
// "연관 함수"라고 불립니다.
//
// 연관 함수는 인스턴스를 통해 호출될 필요가 없습니다.
// 이러한 함수들은 일반적으로 생성자처럼 사용됩니다.
fn origin() -> Point {
Point { x: 0.0, y: 0.0 }
}
// 두 개의 인자를 받는 또 다른 연관 함수:
fn new(x: f64, y: f64) -> Point {
Point { x: x, y: y }
}
}
struct Rectangle {
p1: Point,
p2: Point,
}
impl Rectangle {
// 이것은 메서드입니다
// `&self`는 `self: &Self`를 줄여 쓴 것인데, 여기서 `Self`는
// 호출 객체의 타입을 의미합니다. 이 경우 `Self` = `Rectangle`입니다.
fn area(&self) -> f64 {
// `self`는 점(dot) 연산자를 통해 구조체 필드에 대한 접근을 제공합니다.
let Point { x: x1, y: y1 } = self.p1;
let Point { x: x2, y: y2 } = self.p2;
// `abs`는 호출자의 절댓값을 반환하는 `f64` 메서드입니다.
((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())
}
// 이 메서드는 호출 객체가 가변적일 것을 요구합니다
// `&mut self`는 `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`는 리소스를 소유합니다: 힙에 할당된 두 개의 정수
struct Pair(Box<i32>, Box<i32>);
impl Pair {
// 이 메서드는 호출 객체의 리소스를 "소비"합니다
// `self`는 `self: Self`로 풀어서 쓸 수 있습니다.
fn destroy(self) {
// `self` 구조 분해
let Pair(first, second) = self;
println!("Pair({}, {}) 파괴 중", first, second);
// `first`와 `second`는 스코프를 벗어나며 해제됩니다.
}
}
fn main() {
let rectangle = Rectangle {
// 연관 함수는 이중 콜론을 사용하여 호출됩니다.
p1: Point::origin(),
p2: Point::new(3.0, 4.0),
};
// 메서드는 점 연산자를 사용하여 호출됩니다.
// 첫 번째 인자인 `&self`는 암시적으로 전달됩니다. 즉,
// `rectangle.perimeter()`는 `Rectangle::perimeter(&rectangle)`와 동일합니다.
println!("사각형 둘레: {}", rectangle.perimeter());
println!("사각형 넓이: {}", rectangle.area());
let mut square = Rectangle {
p1: Point::origin(),
p2: Point::new(1.0, 1.0),
};
// 에러! `rectangle`은 불변이지만, 이 메서드는 가변 객체를 요구합니다.
// rectangle.translate(1.0, 0.0);
// TODO ^ 이 줄의 주석을 해제해 보세요
// 좋습니다! 가변 객체는 가변 메서드를 호출할 수 있습니다
square.translate(1.0, 1.0);
let pair = Pair(Box::new(1), Box::new(2));
pair.destroy();
// 에러! 이전의 `destroy` 호출이 `pair`를 "소비"했습니다
// pair.destroy();
// TODO ^ 이 줄의 주석을 해제해 보세요
}