Rust基础复习笔记(二)结构体、枚举与匹配

这一部分涉及到两种新的数据结构:结构体与枚举类型,和一种新的控制流:匹配。
对应The Rust Programming Language第4-5章的内容。代码来自前书。

1.结构体

1.1结构体的定义
一般结构体的定义与其他语言类似:

struct User {
  username: String,
  email: String,
  sign_in_count: u64,
  active: bool,
}
//注意类型名在冒号后声明,变量之间用逗号分隔

如果要声明一个以上的结构体,
可以直接声明:

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: email,
      username,
      active:true,
      sign_in_count:1,
      }
}

从已有的结构体改变几个值以创建新的

fn main() {
    let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

    let user2 = User {
        email: String::from("another@example.com"),
        username: String::from("anotherusername567"),
        ..user1      //这里代表使用user1的其他元素的值
    };
}

另外一种简单的元组结构体使用方法如下:

fn main() {
    struct Color(i32, i32, i32);
    struct Point(i32, i32, i32);

    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
    //注意black和origin是不同的类型,是不能相互运算的。
}

1.2结构体的使用
打印结构体需要启用Debug属性

#[derive(Debug)]      //在这里启用
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!("rect1 is {:?}", rect1);
    println!("rect1 is {:#?}", rect1);//这种方式打印会更加清晰的对输出进行分行操作
}

添加方法:在impl代码块中声明

impl Rectangle {
    fn area(&self) -> u32 {      //参数表中第一项是&self(可变的是&mut self),不含&self的被称为友元函数(?)。
        self.width * self.height
    }
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
    //这种函数一般用来构造。这两个函数也可以分写在不同的impl块中,不过现在没必要。
}

2.枚举

2.1一般枚举类
在enum块中声明,还可以携带一个数据类型(类似于union),这个类型也可以是Tuple或自定义的Struct

enum IpAddr {
    V4(String),
    V6(String),      //没有类型,逗号分隔
}

impl IpAddr{
  fn call(&self){
      /*Anything*/
  }
}
//甚至也可以定义方法
let home = IpAddr::V4(String::from("127.0.0.1");      //声明枚举类型变量及其附属数据
home.call();

Option
rust的基本类型里没有None,但是可以通过Option定义None。

let a1 = Some(1);
let a2:Option<i32> = None;
let a3 = 1;

这三者,a1和a3分属不同类型,不能相加
Option有许多方法和多种用途。这里只介绍基本用途。
匹配
枚举类与匹配天然搭配使用。

#[derive(Debug)]
enum UsState {
    Alabama,
    Alaska,
    // --snip--
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}
//硬币类和四分钱硬币分的各种产地
fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("State quarter from {:?}!", state);//使用参数
            25
        }
    }
}

fn main() {
    value_in_cents(Coin::Quarter(UsState::Alaska));
}

要注意匹配必须把所有情况都列举出来。否则要用占位符:

let some_u8_value = 0u8;
    match some_u8_value {
        1 => println!("one"),
        3 => println!("three"),
        5 => println!("five"),
        7 => println!("seven"),
        _ => (),      //'_'代表占位符,()代表什么也不做
    }

if let匹配,类似于if。可以用来简化match书写的代码。

let mut count = 0;
if let Coin::Quarter(state) = coin {
  println("Quarter from {:?}", state);
} else {
  count += 1;
}
posted @ 2021-01-10 09:26  风坞  阅读(337)  评论(0)    收藏  举报