Rust

[Rust] 구조체의 메소드

dev_dean 2022. 4. 22. 09:26

러스트에서는 구조체에서 사용할 수 있는 함수를 정의할 수 있습니다. 이를 메소드라고 합니다. 

struct Rectangle {
    length: u32,
    width: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.length * self.width
    }
}

fn main() {
    let rect1 = Rectangle { length: 50, width: 30 };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}

메소드는 구조체 밖에서 정의되고 impl [구조체명]로 선언할 수 있습니다. 

메소드의 인자로 존재하는 &self는 메소드를 호출하는 구조체 자체입니다.  self.length 는 rec1의 length인 50을 나타냅니다.

 

구조체의 값을 변경하기 위해서는 &mut self를 사용할 수 있습니다.

struct Rectangle {
    length: u32,
    width: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.length * self.width
    }
    fn bigger(&mut self) {
     	self.length += 10;
        self.width += 10;
    }
}

fn main() {
    let mut rect1 = Rectangle { length: 50, width: 30 };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
    rect1.bigger();
    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}

실행 결과

하지만 구조체의 값을 변경하기 위해선 구조체가 mutable 해야 한다는 것을 명심해야 합니다.

 

더 많은 인자를 가진 메소드 또한 선언 가능합니다.

struct Rectangle {
    length: u32,
    width: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.length * self.width
    }

    fn can_hold(&self, other: &Rectangle) -> bool {
        self.length > other.length && self.width > other.width
    }
}

fn main() {
    let rect1 = Rectangle { length: 50, width: 30 };
    let rect2 = Rectangle { length: 40, width: 10 };
    let rect3 = Rectangle { length: 45, width: 60 };

    println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
    println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
}

can_holde 메소드를 보면 &self 이외에 &Rectangle 타입의 인자를 받는 것을 볼 수 있습니다.

 

연관 함수

impl 블록 안에서 &self 파라미터를 가지지 않는 함수를 연관 함수라고 합니다.

그 이유는 이 함수가 해당 구조체와 연관되어 있기 때문입니다. 이들은 메소드가 아니라 여전히 함수인데, 이는 함께 동작할 구조체의 인스턴스를 가지고 있지 않아서 그렇습니다. 우리가 자주 사용하던 String::from에서 from 또한 연관 함수입니다. 

연관 함수는 구조체를 생성할 때 인스턴스를 반환해주는 생성자로서 자주 사용됩니다.  

impl Rectangle {
    fn square(size: u32) -> Rectangle {
        Rectangle { length: size, width: size }
    }
}

fn main() {
	let sq = Rectangle::square(3); //Rectangle 인스턴스 생성
}

String::from처럼 Rectangle::square(3)로  size를 넘겨주고 생성된 Rectangle 구조체 인스턴스를 sq에 대입하는 것을 볼 수 있습니다.