@Kais(VagrantPi)
Rust
, 簡報
, Rust 讀書會
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
Structs 跟 tuples 很像,一樣可以包含多種 type,跟 tuples 不同的是每個 value 都有一個 key,所以可以清楚知道該值是啥
key: value pairs
不須按造順序
let user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
the struct definition is like a general template for the type, and instances fill in that template with particular data to create values of the type
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: email,
username: username,
// 因為輸入參數名稱跟 struct 變數名稱一樣,所以可以改寫成
// email,
// username,
active: true,
sign_in_count: 1,
}
}
新的 Instance 有部分資料跟使用其他的 Instance 時,
可以透過 struct update syntax(..) 的方法將其餘沒寫到的變數資料補上
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 跟 tuple 的混合型別,取值時是使用 index 值
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let mut black = Color(0, 0, 0);
let origin = Point(1, 2, 3);
println!("{}", origin.1);
// 2
black.0 = 1
println!("{}", black.0);
// 1
v0.1
fn main() {
let width1 = 30;
let height1 = 50;
println!(
"The area of the rectangle is {} square pixels.",
area(width1, height1)
);
// The area of the rectangle is 1500 square pixels.
}
fn area(width: u32, height: u32) -> u32 {
width * height
}
v.02(使用 tuple 重構)
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
}
v.03(使用 struct 重構)
struct Rectangle {
width: u32,
height: u32,
}
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
}
如果是著想印出 struct
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("rect1 is {}", rect1);
// error[E0277]: the trait bound `Rectangle: std::fmt::Display` is not satisfied
// `Rectangle` cannot be formatted with the default formatter; try using
// `:?` instead if you are using a format string
}
println! 在印出東西時 {} 可以包含著格式化特徵(Formatting traits) 而 Display 為預設值
nothing ⇒ Display
? ⇒ Debug
x? ⇒ Debug with lower-case hexadecimal integers
X? ⇒ Debug with upper-case hexadecimal integers
o ⇒ Octal
x ⇒ LowerHex
X ⇒ UpperHex
p ⇒ Pointer
b ⇒ Binary
e ⇒ LowerExp
E ⇒ UpperExp
之所以 Display 能印出原始 type,是因為都們很"單純",所以可以清楚的知道要印出什麼,但 struct 不同,包東包西,struct 的 key
value
間還隔著 :
,所以到底該印那些你並沒有說,而 error
也有建議可以使用 :?
來試試
當你試了之後會發現
// error[E0277]: the trait bound `Rectangle: std::fmt::Debug` is not satisfied
// `Rectangle` cannot be formatted using `:?`; if it is defined in your
// crate, add `#[derive(Debug)]` or manually implement it
#[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 }
}
這樣我們會改用 {:#?}
// rect1 is Rectangle {
// width: 30,
// height: 50
// }
#[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()
);
}
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));
// want
// Can rect1 hold rect2? true
// Can rect1 hold rect3? false
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
}
Associated Functions 通常用於建立一個或某種資料型態(因為會直接 return struct 的 instance)
impl Rectangle {
fn square(size: u32) -> Rectangle {
Rectangle { width: size, height: size }
}
}
let sq = Rectangle::square(3);
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
impl Rectangle {
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
}