Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

연관 함수와 메서드

일부 함수는 특정 타입과 연결되어 있습니다. 이들은 연관 함수와 메서드라는 두 가지 형태로 제공됩니다. 연관 함수는 일반적으로 타입 상에 정의된 함수인 반면, 메서드는 특정 타입의 인스턴스에서 호출되는 연관 함수입니다.

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 ^ 이 줄의 주석을 해제해 보세요
}