5.0 Defining and Instantiating Structs
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
- ๊ธฐ๋ณธ์ ์ผ๋ก ํํ๊ณผ ๋น์ทํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ฌถ์ด์ฃผ๋ ์ญํ ์ ํ๋ค.
- ํํ๋ณด๋ค ๋ ๋ง์ ์ ์ฐ์ฑ์ ์ ๊ณตํ๋ค.
- cpp์ ๊ตฌ์กฐ์ฒด์ ๊ฑฐ์ ๋์ผํ๋ค.
- ts์ ์ธํฐํ์ด์ค์ ์ ์ฌํ๋ค.
struct
ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ํ๋ค.
fn main() {
let user1 = User {
email: String::from("some@example.com"),
username: String::from("someusername"),
active: true,
sign_in_count: 1,
}
.
์ ์ฌ์ฉํ์ฌ ํ๋์ ์ ๊ทผํ ์ ์๋ค.- ๋ง์ฝ instance๊ฐ mutableํ๋ค๋ฉด ํ๋์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค.
- ํ๋์ ์ผ๋ถ๋ mutable์ด๊ณ ์ผ๋ถ๋ immutable์ผ ์ ์๋ค.
fn build_user(email: String, username: String) -> User {
User {
email: email,
username: username,
active: true,
sign_in_count: 1,
}
}
fn build_user2(email: String, username: String) -> User {
User {
email,
username,
active: true,
sign_in_count: 1,
}
}
- ํํ์ ํํ๋ก ํจ์์ ๋ฐํ๊ฐ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
- ํ๋์ ์ด๋ฆ๊ณผ ๋ณ์์ ์ด๋ฆ์ด ๊ฐ๋ค๋ฉด
email: email
์email
๋ก ์ถ์ฝํ ์ ์๋ค.
5.1.1 Creating Instances From Other Instances With Struct Update Syntax
fn main() {
// --snip--
let user2 = User {
email: String::from("another@example.com"),
active: user1.active,
sign_in_count: user1.sign_in_count,
username: user1.username,
};
let user3 = User {
email: String::from("another@example.com"),
..user1
};
}
..
์ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ์ธ์คํด์ค๋ฅผ ๋ณต์ฌํ ์ ์๋ค.- ๋์ค๋ญ์ณ๋ง๊ณผ ๋น์ทํ ๋ฌธ๋ฒ์ด์ง๋ง, ๊ตฌ์กฐ์ฒด๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก iterable trait๋ฅผ ๊ตฌํํ๊ณ ์์ง๋ ์๋๋ค๊ณ ํ๋ค. ์ด๋ป๊ฒ ๊ตฌํ๋์ด์๋์ง ๊ถ๊ธํ๋ค. (์์๋ณด๊ธฐ)
- ์์ ๊ถ ์ด์ ์ ๋์ผํ ๋ ผ๋ฆฌ๋ก ์ผ์ด๋๊ธฐ ๋๋ฌธ์, ๋ง์ฝ stack only data๊ฐ ์๋ ํ๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด, ์ ๋ฐ์ดํธ ์ดํ ๊ธฐ์กด ์ธ์คํด์ค๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค.
5.1.2 Using Tuple Structs without Named Fields to Create Different Types
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
}
-
ํ๋์ ์ด๋ฆ์ด ์๋ ํํ ๊ตฌ์กฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
-
ํ๋์ ์ด๋ฆ์ ๋ถ์ด์ง ์๋ ๊ตฌ์กฐ์ฒด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.
-
ํ๋ฒ ํ์ ์ ์ ์ํ๋ฉด, ๊ทธ ํ๋๋ค์ด ๊ฐ์๋ ๋ค๋ฅธ ํ์ ์ผ๋ก ์ธ์ํ๋ค.
-
black
๊ณผorigin
์ ์๋ก ๋ค๋ฅธ ํ์ ์ด๊ธฐ์, ํจ์ ํ๋ผ๋ฏธํฐ๋ฑ์ผ๋ก ๋ฐ๋๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ์ปดํ์ผ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
5.1.3 Unit-Like Structs Without Any Fields
struct UnitLikeStruct;
fn main() {
let unit_like_struct = UnitLikeStruct;
}
- ํ๋๊ฐ ์๋ ๊ตฌ์กฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
- ์ด๋ฐ ๊ตฌ์กฐ์ฒด๋ ์ ๋ ํ์ ๊ณผ ๋น์ทํ๋ค.
- ๋ฐ์ดํฐํ๋๊ฐ ์๋ trait๋ฅผ ๊ตฌํํ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
- ํ์ ํ๋ผ๋ฏธํฐ๋ ํ ์คํธ์ฉ mock ๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
5.2 An Example Program Using Structs
๊ตฌ์กฐ์ฒด๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์์ฑํ ์ฝ๋๋ฅผ ๊ตฌ์กฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๋ฆฌํฉํ ๋งํ๋ ๊ฐ๋จํ ์์ .
fn main() {
let width1 = 30;
let height1 = 50;
println!(
"The area of the rectangle is {} square pixels.",
area(width1, height1)
);
}
- ํ๋ผ๋ฏธํฐ๊ฐ ๋๊ฐ์ด๋ฉฐ, ํด๋น ๊ฐ๋ค์ด ์ด๋ค ๊ฐ์ธ์ง์ ๋ํ ์ธ์ง๊ฐ ํ์ํด์ ๋ณ๋ก๋ผ๊ณ ํ๋ค.
5.2.1 Refactoring with Tuples
fn main() {
let rect1 = (30, 50);
println!(
"The area of the rectangle is {} square pixels.",
area(rect1)
);
}
fn area(dimensions: (u32, u32)) -> u32 {
dimensions.0 * dimensions.1
}
- ์กฐ๊ธ ๋ ๋ซ๊ธด ํ์ง๋ง, ์๋ฏธ์ ์ผ๋ก
dimensions.0
๊ณผdimensions.1
์ดwidth
์height
๋ผ๋ ๊ฒ์ ์ ์ ์๋ค.
5.2.2 Refactoring with Structs: Adding More Meaning
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!(
"The area of the rectangle is {} square pixels.",
area(&rect1)
);
}
fn area(rectangle: &Rectangle) -> u32 {
rectangle.width * rectangle.height
}
- ๊ตฌ์กฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์๋ค.
- ownership์ ๋๊ธฐ์ง ์๊ณ ์ฐธ์กฐ๋ฅผ ๋๊ธฐ๋ ๊ฒ์ด ์ข๋ค.
5.2.3 Adding Useful Functionality with Derived Traits
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("rect1 is {}", rect1);
}
println!
๋งคํฌ๋ก๋Display
trait๋ฅผ ๊ตฌํํ ํ์ ๋ง ์ฌ์ฉํ ์ ์๋ค, ๊ด๋ จ๋ ์ปดํ์ผ ์๋ฌ๋ฅผ ํ์ธ ํ ์ ์๋ค.
= help: the trait `std::fmt::Display` is not implemented for `Rectangle`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
- ์น์ ํ ์ปดํ์ผ๋ฌ์ ์กฐ์ธ์ ๋ฐ๋ผ
{:?}
๋ฅผ ์ฌ์ฉํด์ ์ถ๋ ฅํ๋ ์์ .
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("rect1 is {:?}", rect1);
}
- ๋ ๋ค๋ฅธ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
= note: `Rectangle` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
Debug
trait๋ฅผ ๊ตฌํํด์ผ ํ๋ค๋ ์๋ฌ์ด๋ค.#[derive(Debug)]
๋ฅผ ์ฌ์ฉํ์ฌDebug
trait๋ฅผ ๊ตฌํํ ์ ์๋ค.- ์ด๋
#[derive(Debug)]
๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํ์ผ๋ฌ๊ฐ ์๋์ผ๋ก ๊ตฌํํ๋๋ก ํ ์ ์๋ค.
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
- ์ด์
{:?}
๋ฅผ ์ฌ์ฉํ์ฌ ์ถ๋ ฅํ ์ ์๋ค. {:?}
๋Debug
trait๋ฅผ ๊ตฌํํ ํ์ ์ ์ถ๋ ฅํ ์ ์๋ค.
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("rect1 is {:?}", rect1);
}
Debug
format์ ์ฌ์ฉํด์ ์ถ๋ ฅํ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์dbg!
๋งคํฌ๋ก๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.dbg!
๋งคํฌ๋ก๋println!
๋งคํฌ๋ก์ ๋น์ทํ์ง๋ง,dbg!
๋งคํฌ๋ก๋ ๊ฐ์ ๋ฐํํ๊ณ , ownership์ ๊ฐ์ ธ๊ฐ๋ค ๋ฐํํด์ค๋ค (println!์ ์ฐธ์กฐ๋ง ๊ฐ์ ธ๊ฐ๋ค.)
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let scale = 2;
let rect1 = Rectangle {
width: dbg!(30 * scale),
height: 50,
};
dbg!(&rect1);
}
$ cargo run
Compiling rectangles v0.1.0 (file:///projects/rectangles)
Finished dev [unoptimized + debuginfo] target(s) in 0.61s
Running `target/debug/rectangles`
[src/main.rs:10] 30 * scale = 60
[src/main.rs:14] &rect1 = Rectangle {
width: 60,
height: 50,
}
5.3 Method Syntax
- ๊ตฌ์กฐ์ฒด์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ ์ ์๋ค.
- ๋ฉ์๋๋ ํจ์์ ๋น์ทํ์ง๋ง, ๊ตฌ์กฐ์ฒด์ ์ธ์คํด์ค์ ๋ํด ํธ์ถ๋๋ค๋ ์ ์ด ๋ค๋ฅด๋ค.
- ๋ฉ์๋๋
self
ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ด์ผ ํ๋ค. self
ํ๋ผ๋ฏธํฐ๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
5.3.1 Defining Methods
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
println!(
"The area of the rectangle is {} square pixels.",
rect1.area()
);
}
-
impl
๋ธ๋ก์ ์ฌ์ฉํ์ฌ ๋ฉ์๋๋ฅผ ์ ์ํ ์ ์๋ค. -
impl
๋ธ๋ก์ ๊ตฌ์กฐ์ฒด์ ์ด๋ฆ๊ณผ ๋ฉ์๋๋ฅผ ๊ตฌํํ ๊ตฌ์กฐ์ฒด์ ์ด๋ฆ์ ๊ฐ์ง๊ณ ์๋ค. -
self
ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ์๋๋ฅผ ํธ์ถํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํฌ ์ ์๋ค. -
self
ํ๋ผ๋ฏธํฐ๋self: &self
์ ์ฝ์ด์ด๋ค. -
Self ํ์ ์ impl ๋ธ๋ก์ด ์ ์ฉ๋๋ ํ์ ์ ๋ณ์นญ์ด๋ค. (
alias
) -
rectangle: &Rectangle
์์์ฒ๋ผ, ์ด ๋ฉ์๋๊ฐ Self ์ธ์คํด์ค๋ฅผ ๋น๋ฆฐ๋ค๋ ๊ฒ์ ๋ํ๋ด๊ธฐ ์ํด self ์ฝ์ด ์์ &๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. -
๋ฉ์๋๋ ๋ค๋ฅธ ๋งค๊ฐ๋ณ์์ฒ๋ผ self์ ์์ ๊ถ์ ๊ฐ์ง ์๋ ์๊ณ , ์ฌ๊ธฐ์ฒ๋ผ self๋ฅผ ๋ถ๋ณ์ผ๋ก ๋น๋ฆด ์๋ ์์ผ๋ฉฐ, ํน์ self๋ฅผ ๊ฐ๋ณ์ผ๋ก ๋น๋ฆด ์๋ ์๋ค.
-
๋ฐ๋๋ก
&mut self
๋ก ์ ์ธํ๋ฉด, ํด๋น ์ธ์คํด์ค๋ฅผ ๊ฐ๋ณ์ผ๋ก ๋น๋ฆด ์ ์๋ค. -
ํน์ ํ ์ธ์คํด์ค๋ฅผ ๋ณํ์ํค๊ณ , ๊ธฐ์กด์ ์ธ์คํด์ค๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํ๊ณ ์ถ๋ค๋ฉด,
&mut self
๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
struct Circle {
radius: f64,
}
impl Circle {
// Circle์ ๋ฉด์ ์ ๊ณ์ฐํ๋ ๋ฉ์๋
fn area(&self) -> f64 {
3.14159 * self.radius * self.radius
}
// Circle์ ๋ฐ์ง๋ฆ์ ์ฃผ์ด์ง ๋ฐฐ์จ๋ก ์กฐ์ ํ๋ ๋ฉ์๋
fn scale(&mut self, factor: f64) {
self.radius *= factor;
}
}
fn main() {
let mut circle = Circle { radius: 5.0 };
println!("์๋ ๋ฉด์ : {}", circle.area());
// circle์ ๋ฐ์ง๋ฆ์ 2๋ฐฐ๋ก ์กฐ์
circle.scale(2.0);
println!("์กฐ์ ๋ ๋ฉด์ : {}", circle.area());
}
impl Circle {
// Circle์ Square๋ก ๋ณํํ๋ ๋ฉ์๋
fn into_square(self) -> Square {
Square { side: self.radius * 2.0 }
}
}
struct Square {
side: f64,
}
fn main() {
let circle = Circle { radius: 5.0 };
let square = circle.into_square(); // ์ฌ๊ธฐ์ circle์ ์์ ๊ถ์ด ์ด๋๋จ
// println!("์์ ๋ฐ์ง๋ฆ: {}", circle.radius); // ์ค๋ฅ: `circle`์ ๋ ์ด์ ์ ํจํ์ง ์์
println!("์ ์ฌ๊ฐํ์ ๋ณ ๊ธธ์ด: {}", square.side);
}
fn main() {
let circle = Circle { radius: 5.0 };
// circle.scale(2.0); // ์ค๋ฅ: `circle`์ ๋ถ๋ณ ์ฐธ์กฐ์ด๋ฉฐ, `scale`์ ๊ฐ๋ณ ์ฐธ์กฐ๋ฅผ ์๊ตฌํจ
}
-
ํจ์ ๋์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ๋จ์ง ๊ตฌ์กฐ์ฒด์์ ํ์ ์ ๋งค๋ฒ ์ฐ์ง ์๊ธฐ ์ํด์๊ฐ ์๋๋ผ, ํด๋น ํ์ ์ ๋ํ method๋ฅผ ์กฐ์งํ ํ๊ธฐ ๋๋ฌธ์ด๋ค. (organization)
-
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด, ํด๋น ํ์ ์ ๋ํ ๋ชจ๋ ๊ธฐ๋ฅ์ ํ ๊ณณ์ ๋ชจ์๋ ์ ์๋ค.
-
ํ๋์ ์ด๋ฆ๊ณผ ๋ฉ์๋์ ์ด๋ฆ์ด ๊ฐ๊ฒ ํ ์ ์๋ค.
-
getter์ ๊ฐ์๊ฒ๋ค๋ ๊ตฌํํ๋๋ฐ, ์ด๊ฑด ๋์ค์..
5.3.2 Where’s the -> Operator?
- (c/cpp ์์)
->
์ฐ์ฐ์๋ ํฌ์ธํฐ์ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ ์ฌ์ฉํ๋ค. ๊ฐ์ฒด์์ ์ง์ ํธ์ถํ๋ ๊ฒฝ์ฐ๋.
- ์ญ์ฐธ์กฐ๋ฅผ ํด์ ํธ์ถํ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ธ๋ฐ,
object
๊ฐ ํฌ์ธํฐ๋ผ๋ฉด,object->method()
๋(*object).method()
์ ๋น์ทํ๋ค. - ๋ฌ์คํธ์์๋ ์ด๋ฌํ ๊ณผ์ ์ด ์๋ํ ๋์ด์๋ค (
automatic referencing and dereferencing
). object.method()
์ ๊ฐ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด, ๋ฌ์คํธ๋ ์๋์ผ๋ก&
,&mut
, *๋ฅผ ์ถ๊ฐํ์ฌ ํธ์ถํ๋ค.
// same
p1.distance(&p2);
(&p1).distance(&p2);
-
์ง์ํ ์ ์๋ฏ์ด self๋ผ๋ ๋ช ํํ ์์ ์๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฅํ๋ค
-
๋ฆฌ์๋ฒ๊ฐ
&self
,&mut self
,self
๋ก ์ ์๋์ด ์๊ธฐ ๋๋ฌธ์, ์ฝ๊ธฐ ์์ ์๋น์ ๋ํ ๋ถ๋ถ์ ๋ช ํํ๊ฒ ํ์ ํ ์ ์๋ค. -
์๋ฅผ ๋ค์ด, ์ด๋ค ๊ฐ์ฒด obj๊ฐ ์๊ณ ์ด ๊ฐ์ฒด์ ๋ํ ๋ฉ์๋ method()๊ฐ ์ ์๋์ด ์์ ๋,
-
Rust๋ obj.method() ํธ์ถ์ ์ ์ ํ๊ฒ ์ฒ๋ฆฌํ๋ค.
-
์ด ๋ฉ์๋๊ฐ &self๋ฅผ ์๊ตฌํ๋ค๋ฉด, Rust๋ ์๋์ผ๋ก &obj.method()๋ฅผ ํธ์ถํ๋ค.
-
๋ง์ฝ ๋ฉ์๋๊ฐ &mut self๋ฅผ ์๊ตฌํ๋ค๋ฉด, Rust๋ &mut obj.method()๋ก ์ฒ๋ฆฌํ๋ค.
-
๊ฐ์ฒด๊ฐ ๊ฐ์ผ๋ก ๋ฉ์๋๋ฅผ ํธ์ถํด์ผ ํ๋ค๋ฉด, Rust๋ ํ์์ ๋ฐ๋ผ (*obj).method()์ฒ๋ผ ์ญ์ฐธ์กฐ๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ค.
5.3.3 Methods with More Parameters
- ๋ฉ์๋๋ ์ถ๊ฐ์ ์ธ ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ง ์ ์๋ค.
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
let rect2 = Rectangle {
width: 10,
height: 40,
};
let rect3 = Rectangle {
width: 60,
height: 45,
};
println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
}
impl Rectangle {
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
}
- self reciever ์ดํ๋ ๊ทธ๋ฅ ์ผ๋ฐ์ ์ธ ํจ์์ ๋์ผํ๋ค.
5.3.4 Associated Functions
-
self ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ง์ง ์๋ ํจ์๋ฅผ
impl
๋ธ๋ก ๋ด์ ์ ์ํ ์ ์๋ค. -
self ํ๋ผ๋ฏธํฐ๊ฐ ์๊ธฐ ๋๋ฌธ์, ๋ฉ์๋๋ ์๋๊ณ
associated function
์ด๋ผ๊ณ ํ๋ค. -
associated function์ ์ฃผ๋ก ๊ตฌ์กฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋๋ฐ ์ฌ์ฉ๋๋ค.
impl Rectangle {
fn square(size: u32) -> Self {
Self {
width: size,
height: size,
}
}
}
- ๋ง์ง๋ง์ผ๋ก impl๋ธ๋ก์ ์ฌ๋ฌ๊ฐ ๋ ์ ์๋๋ฐ, ํฐ ์๋ฏธ๋ ์๋ ๊ฒ ๊ฐ๋ค