Struct的声明和实例化
声明
struct User { username: String, email: String, sign_in_count: u64, active: bool, }
实例化,注意Rust要求每个成员变量的生命周期至少和Struct变量本身一样长
let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, };
在实例化时,如果本地变量和成员变量恰好名字相同,就可以省去成员变量:
fn build_user(email: String, username: String) -> User { User { email, username, active: true, sign_in_count: 1, } }
可以使用旧Struct变量的成员变量来创建一个新的Struct:
let user2 = User { email: String::from("another@example.com"), username: String::from("anotherusername567"), ..user1 };
Tuple Structs
Tuple Struct的意义在于给当前tuple组合一个特定的类型名称,使之和其他的tuple不同,例如:
struct Color(i32, i32, i32); struct Point(i32, i32, i32); let black = Color(0, 0, 0); let origin = Point(0, 0, 0);
Unix-Like Structs
在Rust中,可以定义没有任何成员变量的Struct。因为他们类似(),所以被称为Unit-like structs。这些Structs有助于各种不需要实际数据但是需要依托具体struct的traits的实现。
Traits
struct Rectangle { width: u32, height: u32, } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!("rect1 is {}", rect1); }
println!是一个宏,当它看到{}的时候,就去找对应类型的Display方法,{:?},则取该类型所实现的std::fmt::Debug方法。
为了给Struct Rectangle实现std::fmt::Debug接口,只需要加上[derive(Debug)]这个注解,Rust就能自动地产生最简单的Debug方法。
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!("rect1 is {:#?}", rect1);//与{:?}相比,{:#?}是pretty print style } cargo run Compiling structs v0.1.0 (file:///projects/structs) Finished dev [unoptimized + debuginfo] target(s) in 0.48s Running `target/debug/structs` rect1 is Rectangle {
width: 30,
height: 50,
}
Rust本身已经为我们用derive注解提供了很多默认的行为。
Struct Methods
Method一般第一个参数永远是&self
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 } }//当然可以用多个impl Rectangle块
在调用时,只需简单使用类似v1.can_hold(&v2),而不需要调用(&v1).can_hold(&v2)或者(&mut v1).change_sth(&v2)。这是因为Rust中有automatic referencing和dereferencing机制。在Rust编程时,无需使用pointer->sth()或者(*pointer).sth(),可以理解为,编译器会确定当前method调用是对self对应的变量做read(&self),mutating(&mut self)还是consuming(self),自动地帮代码从obj.sth()变成(&obj).sth()或者(&mut obj).sth()或者obj.sth()
Associated functions
可以定义不把self作为参数的函数,这些函数被称为相关函数(Associated functions),这些函数不是成员方法,例如String::from就不是方法。Associated function一般被用作constructors。