Study Rust Bible analysis - Rust learn-7 (structure and enumeration, Option)

@[TOC](Study Rust Bible Analysis——Rust learn-7(Structure and Enumeration, Option))

structure

Structs are similar to the tuples we discussed in the "Tuple Types" section in that they contain multiple related values. Like tuples, each part of a struct can be of a different type. But unlike tuples, structs need to name each part of the data to clearly indicate the meaning of its values. Because of these names, structs are more flexible than tuples: there is no need to rely on order to specify or access the values ​​in the instance.

declare structure

We declare the structure by using the struct keyword to specify the field type in the structure

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

Constructing an instance of a structure

As follows, we build and use in the code after declaring the structure

#[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);
}

Access fields in a struct

It's easy 结构体名称.字段名称to access

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

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

tuple structure

Define structures similar to tuples, called tuple structs. The tuple structure has the meaning provided by the structure name, but has no specific field names, only the types of the fields. Tuple structs are useful when you want to give the entire tuple a name and make the tuple a different type than other tuples, when naming each field like a regular struct would be redundant and formalized.

For example, I want to define a coordinate point:

struct Pos(f64, f64);

class unit structure

In fact, it is a simple empty structure without any fields, which is used to implement traits. You can understand it as an inheritance body that can be implemented

struct UnitStruct;

Assign methods to the structure

We use the impl key to add the methods required by the structure to the structure.
For example, as follows, we declare a User structure and add a new method to the structure to build a structure.

#[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,
        };
    }
}

Use the method declared in the structure

If you are using the structure directly, you need to use the method to call it::

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

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

self calls itself

In the following program, the parameter of the sout method is &self, that is, calling itself. We can directly use self to obtain fields in the function. Self only depends on your structure methods and fields.

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());
}

enumerate

Enumerations (enum) allow you to define a type by enumerating possible members (variants)

define enumeration

As follows we define an enumeration of parents, using the enum keyword

enum Parent{
    
    
    father,mother
}

use the members of the enum

As follows, use ::to specify members

 let wang = Parent::father;

Define methods for enums

In fact, this is the same as in struct and also uses the impl keyword

enum Parent {
    
    
    father,
    mother,
}

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

self

Using self is actually the same as the structure

#[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();
}

Nest each other

We can nest enumerations in structs and use structs in enumerations

Enumerate nested structures

We build a Person structure and nest it into Parent. The following is a more complete example:

#[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());
}

Nested enums in structs

This example is very simple. Unit is given as a type to the fields in the structure

struct HtmlUnit {
    
    
    unit: Unit,
}

enum Unit {
    
    
    px,
    vh,
    vw,
}

Option

Option is another enum defined by the standard library. The Option type is widely used because it encodes a very common scenario where a value either has a value or has no value. Rust doesn't have the null functionality that many other languages ​​have. A null value (Null) is a value that represents no value. In languages ​​with null values, variables are always in one of two states: null and not-null.

The problem with null values ​​is that when you try to use a null value like a non-null value, some form of error occurs. Because of the ubiquity of empty and non-null properties, it is very easy to make this kind of mistake.
However, the concept that null values ​​try to convey still makes sense: a null value is a value that is currently invalid or missing for some reason.
The problem is not the concept but the concrete implementation. For this reason, Rust doesn't have null values, but it does have an enum that encodes the notion of presence or absence. This enum isOption<T>

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

Some

The Some value in Option can construct a value as a Option<type>return and use the unwrap series to restore it

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

None

Option<T>It must be converted to a T before operating on it . Often this helps us catch one of the most common problems with null values: the case where a value is supposed to be not null but it is.

Eliminating the risk of incorrectly assuming a non-null value will give you more confidence in your code. In order to have a possibly nullable value, you have to explicitly put it in the corresponding type Option<T>. Then, when using this value, you must explicitly handle the null case. As long as a value is not Option<T>of type , you can safely assume that its value is not null.

 let b: Option<i32> = None;

Guess you like

Origin blog.csdn.net/qq_51553982/article/details/130181778