在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
A struct, or structure, is a custom data type that lets you name and package together multiple related values that make up a meaningful group. Defining and Instantiating Structs相比元组,struct中的属性是无序的 To define a struct, we enter the keyword struct User { username: String, email: String, sign_in_count: u64, active: bool, } let user1 = User { email: String::from("[email protected]"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; 如果其属性可能被修改,那么其实例必须声明为mut可变类型 let mut user1 = User { email: String::from("[email protected]"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; user1.email = String::from("[email protected]"); Note that the entire instance must be mutable; Rust doesn’t allow us to mark only certain fields as mutable. As with any expression, we can construct a new instance of the struct as the last expression in the function body to implicitly return that new instance. fn build_user(email: String, username: String) -> User { User { email: email, username: username, active: true, sign_in_count: 1, } } we can use the field init shorthand syntax to rewrite fn build_user(email: String, username: String) -> User { User { email, username, active: true, sign_in_count: 1, } }
Creating Instances From Other Instances With Struct Update SyntaxIt’s often useful to create a new instance of a struct that uses most of an old instance’s values but changes some. You’ll do this using struct update syntax. let user2 = User { email: String::from("[email protected]"), username: String::from("anotherusername567"), active: user1.active, sign_in_count: user1.sign_in_count, }; The syntax let user2 = User { email: String::from("[email protected]"), username: String::from("anotherusername567"), ..user1 };
完整示例 fn main() { println!("Hello, struct!"); update_user(); let user2: User = build_user("[email protected]".to_string(),"mysql".to_string()); print_user(&user2); let user3: User = User{ username: "[email protected]".to_string(), email: "[email protected]".to_string(), ..user2 }; print_user(&user3); } struct User{ username: String, email: String, userid: u64, active: bool, } fn print_user(user1: &User){ println!("{},{},{},{}",user1.username,user1.email,user1.userid,user1.active); } fn update_user(){ let mut user1 = User{ username: String::from("用户名"), email: String::from("[email protected]"), userid: 1, active: true, }; user1.active = false; print_user(&user1) } fn build_user(email: String, username: String) -> User { User { email, username, active: true, userid: 1, } }
运行结果 Finished dev [unoptimized + debuginfo] target(s) in 0.01s Running `target/debug/b_struct` Hello, struct! 用户名,[email protected],1,false mysql,[email protected],1,true [email protected],[email protected],1,true
Using Tuple Structs without Named Fields to Create Different Types元组结构体,无字段名称,有元组的特性 fn test_tu(){ let _tup: (i32, f64, u8) = (500, 6.4, 1); let _aa = (1,2.3,"wa ka ka "); let (_x,_y,_z) = _aa; println!("The value of z is:{}",_z); struct Color(i32, i32, i32); struct Point(i32, i32, i32); let black = Color(0, 0, 0); let origin = Point(0, 0, 0); println!("color:{},{},{}",black.0,black.1,black.2); println!("origin:{},{},{}",origin.0,origin.1,origin.2); } 输出 The value of z is:wa ka ka color:0,0,0 origin:0,0,0 ownership,引用只能作用于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 fn main() { println!("Hello, struct!"); test_user(); } #[derive(Debug)] struct User{ username: String, email: String, userid: u64, active: bool, } fn test_user(){ let u1 = User{ username: "败者千千万,胜者唯一人".to_string(), email: "[email protected]".to_string(), userid: 123, active: false, }; println!("user:{:?}",u1); } 输出 Hello, sturct! user:User { username: "败者千千万,胜者唯一人", email: "[email protected]", userid: 123, active: false }
fn main() { println!("Hello, struct!"); test_user(); } #[derive(Debug)] struct User{ username: String, email: String, userid: u64, active: bool, } fn test_user(){ let u1 = User{ username: "败者千千万,胜者唯一人".to_string(), email: "[email protected]".to_string(), userid: 123, active: false, }; println!("user:{:#?}",u1); } 输出 Hello, struct! user:User { username: "败者千千万,胜者唯一人", email: "[email protected]", userid: 123, active: false, }
结构体方法分两类:Methods、Associated Functions Methods:实例相关,第一个参数必须为&self或&mut self,调用方式为 实例.方法名 Associated Functions:struct相关,无须传入self参数,跟实例没关系,是关联在struct上的,相当基于Java语言中的静态方法,调用方式为 struct名称::方法名 Methods#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { //impl -> implementation fn area(&self) -> u32 { //self -> rectangle: &Rectangle self.width * self.height } } fn main() { let rect1 = Rectangle { width: 30, height: 50 }; println!( "The area of the rectangle is {} square pixels.", rect1.area() ); } In the signature for We’ve chosen Rust自动处理了对象对其方法或属性的调用 上面的例子中,方法传入的参数&self是引用类型,但其调用属性的时候使用的是self.width,其等价于(&self).width In C and C++, two different operators are used for calling methods: you use . if you’re calling a method on the object directly and -> if you’re calling the method on a pointer to the object and need to dereference the pointer first. In other words, if object is a pointer, object->something() is similar to (*object).something(). 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); The first one looks much cleaner. This automatic referencing behavior works because methods have a clear receiver—the type of self. Given the receiver and name of a method, Rust can figure out definitively whether the method is reading (&self), mutating (&mut self), or consuming (self). The fact that Rust makes borrowing implicit for method receivers is a big part of making ownership ergonomic in practice.
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { //impl -> implementation fn area(&self) -> u32 { //self -> rectangle: &Rectangle (&self).width * self.height } fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.height > other.height } } fn main() { let rect1 = Rectangle { width: 30, height: 50 }; println!( "The area of the rectangle is {} square pixels.", rect1.area() ); 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)); } 输出 The area of the rectangle is 1500 square pixels. Can rect1 hold rect2? true Can rect1 hold rect3? false
Associated FunctionsAnother useful feature of impl Rectangle { fn square(size: u32) -> Rectangle { Rectangle { width: size, height: size, } } } To call this associated function, we use the
struct方法的首个参数必须是&self,或者self &self以引用的方式使用,不涉及ownership self 会生发ownership转移,调用一次后,不能再使用该对象 推荐使用&self
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(&self) -> u32 { self.width * self.height } fn init(&mut self, w: u32,h: u32) { self.width = w; self.height = h; } } pub fn test1() { let mut r1 = Rectangle {width:10, height:30}; println!( "area:{}", r1.area() ); r1.init(10,20); println!( "area:{}", r1.area() ); }
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论