5.1 구조체 정의와 초기화
struct User { username: String, email: String, sign_in_count: u64, active: bool, }
let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, };
구조체 갱신법
let user2 = User { email: String::from("another@example.com"), username: String::from("anotherusername567"), active: user1.active, sign_in_count: user1.sign_in_count, };
아래와 같다.
let user2 = User { email: String::from("another@example.com"), username: String::from("anotherusername567"), ..user1 };
튜플 구조체
struct Color(i32, i32, i32); struct Point(i32, i32, i32); let black = Color(0, 0, 0); let origin = Point(0, 0, 0);
black
과origin
은 서로 다른 자료형이다.
유사 유닛 구조체
()
와 같이 아무런 데이터가 없는 구조체도 작성 가능. 트레일을 사용할 때 유용.
구조체의 소유권
- 구조체 안에서 참조자를 사용할 경우 반드시 life time을 지정해 주어야 한다.
struct User { username: &str, email: &str, sign_in_count: u64, active: bool, } fn main() { let user1 = User { email: "someone@example.com", username: "someusername123", active: true, sign_in_count: 1, }; }
error[E0106]: missing lifetime specifier --> | 2 | username: &str, | ^ expected lifetime parameter error[E0106]: missing lifetime specifier --> | 3 | email: &str, | ^ expected lifetime parameter
5.2. 구조체를 이용한 예제 프로그램
- 사각형의 넓이를 구해보자
struct Rectangle { length: u32, width: u32, } fn main() { let rect1 = Rectangle { length: 50, width: 30 }; println!("rect1 is {}", rect1); } fn area(rectangle: &Rectangle) -> u32 { rectangle.length * rectangle.width }
error[E0277]: the trait bound `Rectangle: std::fmt::Display` is not satisfied
- trait: 일종의
protocol
이나interface
느낌인데, 자료형이 꼭 해야하는 일을 명시해 준 것이라 생각하면 편할 듯.
println!
매크로로{ }
를 사용하여 무언가를 출력하려면std::fmt::Display
트레잇을 구현해야 한다.
println!
매크로로 디버그를 위해서{:?}
를 사용하려면std::fmt::Debug
트레잇을 구현하거나 구조체 선언부 앞에#[derive(Debug)]
를 사용한다.
#[derive(Debug)] struct Rectangle { length: u32, width: u32, } fn main() { let rect1 = Rectangle { length: 50, width: 30 }; println!("rect1 is {:?}", rect1); }
5.3 메소드 문법
- 메소드: 구조체 안에 들어있는 함수.
#[derive(Debug)] 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
.
연관 함수
- static 함수나 class 메서드 같은 역할. 호출할 때는
.
대신에::
를 사용.
impl Rectangle { fn square(size: u32) -> Rectangle { Rectangle { length: size, width: size } } }
- 위의 함수는
let sq = Rectangle::square(3);
처럼 호출 가능.
.
vs ::
.
은 인스턴스에 묶인 함수, 즉 메소드를 호출한다.
::
은 타입이나 모듈에 있는 함수나 이름을 의미한다.