구조체
이해
- 기본 문법
// 형식 선언 struct User { active: bool, username: String, email: String, sign_in_count: u64, } // 인스턴스화 let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; // 접근 및 수정 let mut user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; user1.email = String::from("anotheremail@example.com"); // 필드 초기화 축약 fn build_user(email: String, username: String) -> User { User { email, username, active: true, sign_in_count: 1, } } // 구조체 업데이트 let user2 = User { email: String::from("another@example.com"), ..user1 } // 여기서 user1이 move됩니다. user1.username(String 형식)이 user2.username으로 move되기 때문입니다. // user2를 초기화할 때 username에 별도로 값을 지정하면 user1은 move되지 않습니다. - 메서드
struct impl 내부의 function을 method 또는 associated function이라고 하며, method와 field는 같은 이름을 가질 수 있습니다.
여러 impl이 동시에 존재할 수 있습니다.
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(&self) -> u32 { // method self.width * self.height } fn width(&self) -> bool { // method 与 field 可以同名 self.width > 0 } fn square(size: u32) -> Rectangle { // 不带 &self 也可以 Rectangle { width: size, height: size, } } } // 여러 impl이 동시에 존재할 수 있습니다. impl Rectangle { fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.height > other.height } } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!( "The area of the rectangle is {} square pixels.", rect1.area() ); if rect1.width() { println!("The rectangle has a nonzero width; it is {}", rect1.width); } }
출처
…
Creating Instances From Other Instances With Struct Update Syntax
기존 인스턴스의 값을 대부분 사용하면서 일부만 바꾼 새로운 구조체 인스턴스를 만드는 일은 자주 유용합니다. 구조체 업데이트 문법을 사용하면 됩니다.
먼저 목록 5-6에서는 업데이트 문법 없이 user2에 새로운 User 인스턴스를 만드는 방법을 보여 줍니다. email에는 새 값을 지정하고, 나머지는 목록 5-2에서 만든 user1의 값을 그대로 사용합니다.
let user2 = User {
active: user1.active,
username: user1.username,
email: String::from("another@example.com"),
sign_in_count: user1.sign_in_count,
};
Listing 5-6: Creating a new User instance using one of the values from user1
구조체 업데이트 문법을 사용하면 목록 5-7처럼 더 적은 코드로 같은 효과를 낼 수 있습니다. .. 문법은 명시적으로 설정하지 않은 나머지 필드가 지정한 인스턴스의 해당 필드와 같은 값을 가져야 한다는 뜻입니다.
let user2 = User {
email: String::from("another@example.com"),
..user1
};
Listing 5-7: Using struct update syntax to set a new email value for a User instance but use the rest of the values from user1
목록 5-7의 코드도 user2에 email은 다른 값을 가지지만 username, active, sign_in_count 필드는 user1과 같은 인스턴스를 만듭니다. 남은 필드가 user1의 대응 필드에서 값을 가져오도록 하려면 ..user1은 마지막에 와야 합니다. 그러나 구조체 정의에 나온 필드 순서와 관계없이 원하는 여러 필드의 값을 어떤 순서로든 지정할 수 있습니다.
구조체 업데이트 문법은 데이터를 move하므로 =를 사용한 대입과 비슷하다는 점에 유의하세요. 이는
“변수와 데이터의 상호작용: Move” 절
에서 본 내용과 같습니다. 이 예에서는 user1의 username 필드에 있는 String이 user2로 이동했으므로 user2를 만든 뒤에는 user1을 더 사용할 수 없습니다. 만약 user2의 email과 username 모두에 새로운 String 값을 지정해 user1에서는 active와 sign_in_count 값만 사용했다면, user2를 만든 뒤에도 user1은 여전히 유효합니다. active와 sign_in_count의 형식은 Copy trait을 구현하므로
“스택 전용 데이터: Copy” 절
에서 설명한 동작이 적용됩니다.