-
[Rust] 5. struct에 대하여rust 2023. 1. 31. 23:13반응형
https://doc.rust-lang.org/book/ch05-01-defining-structs.html
링크를 복습하면서 정리하는 글이며 js 나 solidity 를 사전지식으로 하는상황에서 비슷한 부분은 정리하지 않은 글이다.
Struct Type
> 기본구조
struct User { active: bool, username: String, email: String, sign_in_count: u64, }
- 다양한 타입의 필드를 가지고 있고 순서에 상관 없이 필드에따라 값을 지정해줄수 있다.
> 인스턴스 생성 과 syntax
let user1 = User { active: true, username: String::from("someusername123"), email: String::from("someone@example.com"), sign_in_count: 1, };
- 위와같이 해당 타입으로 인스턴스를 생성하수 있다.
- 인스턴스 생성자 함수를 사용하는 경우 같은 네이밍은 shortcut 을 사용할수 있다.
- 다른인스턴스를 바탕으로 생성하는경우 .. syntax 를 사용할수 있으며 구문특징은 js 의 spread syntax(...) 와 같다.
- 다른인스턴스를 바탕으로 생성하는경우 다른인스턴스에 힙데이터가 존재한다면 소유권 이전이 일어나면 이후에 해당인스턴스는 유효하지 않을수 있다는 점은 유의해야한다.
> 인스턴스 접근 및 변경
fn main() { let mut user1 = User { ... }; user1.email = String::from("anotheremail@example.com"); }
- dot notation 으로 접근 및 변경 이 가능 하지만 변경할때는 역시 인스턴스 생성시 변수는 mut 키워드로 생성되어야한다.
> tuple struct
struct Color(i32, i32, i32); struct Point(i32, i32, i32); fn main() { let black = Color(0, 0, 0); let origin = Point(0, 0, 0); let tup: (i32, f64, u8) = (500, 6.4, 1); }
- tuple struct 형태로 field 의 name 없이 사용하는 sturct 형태이며 tuple처럼 구조분해하거나 dot notation 으로 index 로 접근할수있다.
> unit-like struct
struct AlwaysEqual; fn main() { let subject = AlwaysEqual; }
- unit-like struct 형태로 filed 자체가 존재하지 않는 struct 형태이다 어떤 목적으로 쓰이는지는 잘모르겠는데 ch10 에서 trait 과 관련해서 사용되는 부분이 있다고 하니 그때한번 봐야겠다.
> reference in filed type
struct User { active: bool, username: &str, email: &str, sign_in_count: u64, }
- filed type에 reference 를 사용할수는 있지만 그럴경우 lifetime에 대한 표시가 있어야 한다고한다. 그부분도 ch10 에 있다고 하니 그때다시 봐야겠다.
> debug trait
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!("rect1 is {:?}", rect1); //rect1 is Rectangle { width: 30, height: 50 } println!("rect1 is {:#?}", rect1); // rect1 is Rectangle { width: 30, height: 50, } }
- #[derive(Debug)] 이부분을 trait 이라고 하는거 같다.
- 원시유형과 다르게 구조체는 Display 하기 위한 implementation 을 가지고 있지 않아 trait 을 통해 Debug할수 있는 implemtation 을 상속받아야 print 할수 있게된다.
- :#? :? 와 같은 문자를 통해 디버그 format 을 지정할수 있다.
> method
struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(&self) -> u32 { self.width * self.height } }
- impl 키워드를 통해 원하는 구조체의 메서드를 생성할수도 있다.
- 메서드의 첫번째인자로는 메서드를 호출하는 인스턴스를 self 로 칭하며 사용할수 있고 참조자형태로 주로 사용한다.
- 메서드는 소유권을 가져올수도 있고 borrow 해서 사용할수도 있으며 mutable 하게 borrow 할수도 있다. 즉 self , &self, &mut self 와 같은 형태로 사용가능하니 필요에 맞게 설정할수 있다.
- 다만 self 그대로 사용하는 경우 소유권이 move 됨으로 이후 origin instance 를 사용할수 없으니 주의해야한다.
- 더많은 인자를 필요로 하는경우 self 이후로 순서대로 받아 사용하면 된다.
> associated function
impl Rectangle { fn square(size: u32) -> Self { Self { width: size, height: size, } } }
- 위와같이 self를 인자로 사용하지 않는 함수도 impl 키워드를 통해 struct에 정의 할수 있는데 이런 함수는 method 라고 부르지 않고 associated function 이라고 부른다.
- associated function 은 self 를 첫번째 인자로 받아 사용하지는 않지만 함수안에서 Self 라는 키워드는 사용할수 있는데 여기서 Self 는 이는 해당 struct type 을 지칭한다.
- method 는 인스턴스에 dot notation 으로 접근해서 사용했지만 associated function은 해당 타입에 :: syntax 를 통해 접근해서 사용할수 있다.
- 잘알고 있는 예시로 String::from("asdf") funtion 이 있는데 이처럼 struct::funcname(param) 형태로 사용하면된다.
- 위의 예시의 사용은 lec rect = Rectangle::squre(3)
> 잘 이해안가는 부분
Rust doesn’t have an equivalent to the -> operator; instead, Rust has a feature called automatic referencing and dereferencing. Calling methods is one of the few places in Rust that has this behavior.
Here’s how it works: when you call a method with object.something(), Rust automatically adds in &, &mut, or * so object matches the signature of the method. In other words, the following are the same:
p1.distance(&p2); (&p1).distance(&p2);
'rust' 카테고리의 다른 글
[Rust] 6. enum과 match에 대하여 (0) 2023.02.02 [Defi] 디파이 시작해보기(1) (0) 2023.02.01 [Rust] 4.ownership(3). slice (0) 2023.01.28 [Rust] 4. ownership(2).함수와 ownership (0) 2023.01.28 [Rust] 4. ownership(1). ownership, 변수와 ownership (0) 2023.01.28