本文的参考代码在这里
定义及实例化结构 Struct struct
关键字,中文可以理解为结构体, 是一种自定义数据类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 struct User { username: String , active: bool , email: String , sign_in_count: u64 } fn main () { let mut user1 = User { username: String ::from("user1" ), email: String ::from("[email protected] " ), active: true , sign_in_count: 1 }; }
改变实例中的值,可以直接用点 .
进行访问及赋值,如:
1 2 3 4 5 6 let name = user1.username;user1.username = String ::from("John123" ); println! ( "username before: {}, username after: {}" , name, user1.username );
Field Init
简写用函数生成实例:封装一个函数用于生成 User 对象,再生成一个 user2
的实例
当生成 user3
时,如果其他属性不想列出,可以直接用 ..
的语法拿取 user2
中的参数直接使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 fn main () { let user2 = build_user( String ::from("[email protected] " ), String ::from("kyle123" ) ); println! ("user2.username => {}, user3.email after => {}" , user2.username, user2.email); let user3 = User { email: String ::from("[email protected] " ), username: String ::from("james234" ), ..user2 }; println! ("user3.username {}, user3.email {}" , user3.username, user3.email); } fn build_user (email: String , username: String ) -> User { User { email, username, active: true , sign_in_count: 1 } }
tuple struct
使用元组结构创建不同类型1 2 3 struct Color (i32 , i32 , i32 );struct Point (i32 , i32 , i32 );
以下的代码是一个普通的计算长方形面积的函数:
1 2 3 4 5 6 7 8 9 10 fn main () { let width1 = 30 ; let height1 = 50 ; println! ("area of the reactangle is {}" , area(width1, height1)); } fn area (width: u32 , height: u32 ) -> u32 { width * height }
将其传参改为元组,则可以改写成:
1 2 3 4 5 6 7 8 fn main () { let rect = (30 , 50 ); println! ("area of the reactangle is {}" , area_by_tuple(rect)); } fn area_by_tuple (dimensions: (u32 , u32 )) -> u32 { dimensions.0 * dimensions.1 }
将元组的部分提炼成 struct
, 改写成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 struct Rectangle { width: u32 , height: u32 } fn main () { let rect1 = Rectangle { width: 30 , height: 50 }; println! ("rect1 {:?}" , rect1); println! ("the area of the reactangle is {}" , area_by_struct(&rect1)); } fn area_by_struct (rectangle: &Rectangle) -> u32 { rectangle.width * rectangle.height }
tips:在我们定义了 let rect1
后我们是无法直接打印出来的,会报错,这时,我们需要在 struct Rectangle
上加一个修饰符 #[derive(Debug)]
,而且打印里的{}也需要加上,才能正确打印出 rect1
,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #[derive(Debug)] struct Rectangle { width: u32 , height: u32 } fn main () { let rect1 = Rectangle { width: 30 , height: 50 }; println! ("rect1 {:?}" , rect1); println! ("rect1 {:#?}" , rect1); }
以上涉及到 trait
特征的概念,我们后面的章节会讲到
方法 Method Syntax 定义方法 上面的 struct
由于有固定的公式,即width*height
我们可以把他简化为 impl
, 将area的计算公式定义在其内部,少写了一个函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #[derive(Debug)] struct Rectangle { width: u32 , height: u32 } impl Rectangle { fn area_by_impl (&self ) -> u32 { self .width * self .height } fn can_hold (&self , other: &Rectangle) -> bool { self .width > other.width && self .height > other.height } } fn main () { let rect2 = Rectangle { width: 33 , height: 55 }; println! ("the area of the reactangle is {}" , rect2.area_by_impl()); let rect3 = Rectangle { width: 22 , height: 33 }; let rect4 = Rectangle { width: 66 , height: 77 }; println! ("rect2 can hold rect3 {}" , rect2.can_hold(&rect3)); println! ("rect2 can hold rect4 {}" , rect2.can_hold(&rect4)); }
关联函数 尽管官方文档有很多解释,但简单来说就是 impl
能直接像普通函数一样传入参数,我们来看一个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 impl Rectangle { fn square (size: u32 ) -> Self { Self { width: size, height: size } } } fn main () { let rect5 = Rectangle::square(22 ); println! ("rect5 {:?}" , rect5); }
需要注意,关联函数需要用 ::
进行函数传值,而不是点。