研读Rust圣经解析——Rust learn-7(结构体与枚举,Option)

@[TOC](研读Rust圣经解析——Rust learn-7(结构体与枚举,Option))

结构体

结构体和我们在“元组类型”部分论过的元组类似,它们都包含多个相关的值。和元组一样,结构体的每一部分可以是不同类型。但不同于元组,结构体需要命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字,结构体比元组更灵活:不需要依赖顺序来指定或访问实例中的值。

声明结构体

我们通过使用struct关键字对结构体进行声明,指定结构体中的字段类型

struct User{
    
    
    id:i32,
    username:String,
    pwd:String,
}

构造结构体实例

如下,我们在声明结构体后在代码中进行构建使用

#[derive(Debug)]
struct User {
    
    
    id: i32,
    username: String,
    pwd: String,
}

fn main() {
    
    
    let user = User {
    
    
        id: 1,
        username: "zhangsan".to_string(),
        pwd: "123455".to_string(),
    };
    println!("{:#?}", user);
}

访问结构体中的字段

这很简单结构体名称.字段名称即可访问了

fn main() {
    
    
    let user = User {
    
    
        id: 1,
        username: "zhangsan".to_string(),
        pwd: "123455".to_string(),
    };

    println!("{:?}", user.username);
}

元组结构体

定义与元组类似的结构体,称为 元组结构体(tuple structs)。元组结构体有着结构体名称提供的含义,但没有具体的字段名,只有字段的类型。当你想给整个元组取一个名字,并使元组成为与其他元组不同的类型时,元组结构体是很有用的,这时像常规结构体那样为每个字段命名就显得多余和形式化了。

好比我要定义一个坐标点:

struct Pos(f64, f64);

类单元结构体

其实就是一个简单的空结构体,里面没有任何字段,用于实现trait你可以将其理解为一个可供实现的继承体

struct UnitStruct;

为结构体赋予方法

我们通过使用impl关键为结构体内添加结构体需要的方法
例如以下,我们声明了一个User结构体,为结构体添加了一个new方法以构建一个结构体

#[derive(Debug)]
struct User {
    
    
    id: i32,
    username: String,
    pwd: String,
}

impl User {
    
    
    fn new(id: i32, username: String, pwd: String) -> User {
    
    
        return User {
    
    
            id,
            username,
            pwd,
        };
    }
}

使用结构体中声明的方法

如果你是直接使用结构体的话,调用其中的方法就需要使用::

fn main() {
    
    
   let user =User::new(1,"zhangsan".to_string(),"sdjk".to_string());

    println!("{:#?}", user);
}

self调用自身

如下一段程序中sout方法的参数是&self也就是调用了自身,我们在函数中就可以直接使用self获取字段,self只取决于你的结构体方法、字段有哪些。

impl User {
    
    
    fn new(id: i32, username: String, pwd: String) -> User {
    
    
        return User {
    
    
            id,
            username,
            pwd,
        };
    }
    fn sout(&self) -> String {
    
    
        return self.username.to_string() + "---" + &self.pwd;
    }
}

fn main() {
    
    
    let user = User::new(1, "zhangsan".to_string(), "sdjk".to_string());

    println!("{:#?}", user);
    println!("{}", user.sout());
}

枚举

枚举(enum)允许你通过列举可能的 成员(variants)来定义一个类型

定义枚举

如下我们定义了一个父母的枚举,使用enum关键字

enum Parent{
    
    
    father,mother
}

使用枚举中的成员

如下,使用::即可指定成员

 let wang = Parent::father;

为枚举定义方法

其实这和struct中是一样的也是使用impl关键字

enum Parent {
    
    
    father,
    mother,
}

impl Parent {
    
    
    fn getFather() -> Parent {
    
    
        return Parent::father;
    }
}
let wang = Parent::getFather();

self

使用self其实也和结构体一样的

#[derive(Debug)]
enum Parent {
    
    
    father,
    mother,
}

impl Parent {
    
    
    fn getFather() -> Parent {
    
    
        return Parent::father;
    }
    fn sss (&self)->(){
    
    
       println!("{:?}", self::father)
    }
}

fn main(){
    
    
    let wang = Parent::getFather();
    wang.sss();
}

相互嵌套

我们既可以在结构体里嵌套枚举也可以在枚举中使用结构体

枚举嵌套结构体

我们构建一个Person结构体,嵌套入Parent中,以下是一个较为完整的示例:

#[derive(Debug)]
struct Person {
    
    
    name: String,
    age: i32,
    height: f64,
    weight: f64,
}

#[derive(Debug)]
enum Parent {
    
    
    father {
    
    
        name: String,
        age: i32,
    },
    mother(Person),
}

impl Parent {
    
    
    fn getFather(&self) -> Parent {
    
    
        return self::father {
    
    
            name: "zhansgan".to_string(),
            age: 26,
        };
    }
}

fn main() {
    
    
    let wang = Parent::mother(Person {
    
    
        name: "wang".to_string(),
        age: 26,
        height: 167.6,
        weight: 104.5,
    });
    println!("{:#?}", wang);
    let li = Parent::father {
    
    
        name: "li".to_string(),
        age: 32,
    };
    println!("{:?}", li);
    println!("{:?}",li.getFather());
}

结构体中嵌套枚举

这个示例就很简单了,将Unit作为类型给到了结构体中的字段

struct HtmlUnit {
    
    
    unit: Unit,
}

enum Unit {
    
    
    px,
    vh,
    vw,
}

Option

Option 是标准库定义的另一个枚举。Option 类型应用广泛因为它编码了一个非常普遍的场景,即一个值要么有值要么没值。Rust 并没有很多其他语言中有的空值功能。空值(Null )是一个值,它代表没有值。在有空值的语言中,变量总是这两种状态之一:空值和非空值。

空值的问题在于当你尝试像一个非空值那样使用一个空值,会出现某种形式的错误。因为空和非空的属性无处不在,非常容易出现这类错误。
然而,空值尝试表达的概念仍然是有意义的:空值是一个因为某种原因目前无效或缺失的值。
问题不在于概念而在于具体的实现。为此,Rust 并没有空值,不过它确实拥有一个可以编码存在或不存在概念的枚举。这个枚举是 Option<T>

enum Option<T> {
    
    
    None,
    Some(T),
}

Some

Option中的Some值可以将一个值构建为Option<type>返回使用unwrap系列可以还原出来

fn main() {
    
    
    let a: Option<String> = Some(String::from("nihao"));
    println!("{}", a.unwrap())
}

None

在对Option<T>进行运算之前必须将其转换为 T。通常这能帮助我们捕获到空值最常见的问题之一:假设某值不为空但实际上为空的情况。

消除了错误地假设一个非空值的风险,会让你对代码更加有信心。为了拥有一个可能为空的值,你必须要显式的将其放入对应类型的Option<T>中。接着,当使用这个值时,必须明确的处理值为空的情况。只要一个值不是 Option<T> 类型,你就 可以 安全的认定它的值不为空。

 let b: Option<i32> = None;

猜你喜欢

转载自blog.csdn.net/qq_51553982/article/details/130181778