命名结构体 有些也称作为具名结构体,就是指每个字段都有名字的结构体,它的每个字段都有明确的名字和类型。 #[derive(Debug)]
struct Person {
    name: String,
    age: u32,
    role: String,
}
struct _Society {
    year: u32,
    persons: Vec<Person>,   // struct可作为另一个struct的变量类型
}
fn main() {
    let farmer = Person {
        name: String::from("ohBug"),
        age: 18,
        role: String::from("Farmer"),
    };
    let name = String::from("Qidai");
    let age = 22;
    let mut busi_man = Person {
        name,
        age,
        role: String::from("busi_man"),
    };
    println!("busi_man = {:?}", busi_man);
    println!("Farmer = {:?}", farmer);
    // 更新字段,注意busi_man是mut修饰
    busi_man.name = String::from("beggar");
    println!("busi_man = {:?}", busi_man);
    let busi_man_name = busi_man.name;
    println!("busi_man_name = {}", busi_man_name);
    // error 因为name字段是String类型,所以有所有权概念,现在所有权已经归属于 busi_man_name,所以不能整体打印 busi_man
    // println!("busi_man = {:?}", busi_man);
    // 但是可以打印没有被影响的字段
    println!("busi_man = {:?}", busi_man.role);
    let farmer_two = Person {
        name: String::from("twoxx"),
        age: 45,
        ..farmer   // farmer的role并不会变,可使用此种赋值方式。
    };
    println!("farmer_two = {:?}", farmer_two)
}
// output 
busi_man = Person { name: "Qidai", age: 22, role: "busi_man" }
Farmer = Person { name: "ohBug", age: 18, role: "Farmer" }
busi_man = Person { name: "beggar", age: 22, role: "busi_man" }
busi_man_name = beggar
busi_man = "busi_man"
	farmer_two = Person { name: "twoxx", age: 45, role: "Farmer" }匿名结构体 #[derive(Debug)]
struct point_2d {
    x: i32,
    y: i32,
}
#[derive(Debug)]
struct circle_2d {
    point: point_2d,
    radius: i32,
}
// 元组结构体,对于一些结构描述的更加清晰直接
#[derive(Debug)]
struct circle((i32, i32), i32);
fn main() {
    let point = point_2d { x: 31, y: 42 };
    let _circle = circle_2d { point, radius: 12 };
    println!("{:?}", _circle);
    // 元组结构体
    let tuple_circle = circle((31, 42), 12);
    println!("{:?}", tuple_circle);
}
// output 
circle_2d { point: point_2d { x: 31, y: 42 }, radius: 12 }
circle((31, 42), 12)单元结构体 #[derive(Debug)]
struct FLAG;
fn main() {
    let flag = FLAG;
    println!("{:?}", flag)
}
//ouput 
FLAG面向对象 构造方法 // Default 默认构造器,就是将Person初始化的时候,对象中的各个字段都是默认值
#[derive(Debug, Default)]
struct Person {
    name: String,
    age: u32,
}
impl Person {
    // 构造,new只是方法名,并非强制
    fn new(name: &str, age: u32) -> Person{
        Person {
            name: name.to_string(), age,
        }
    }
}
fn main() {
    let person = Person::new("ohBug", 20);
    println!("{:?}", person);
    let default_person = Person::default();
    // 与上面作用一样
    // let default_person: Person = Default::default();
    println!("{:?}", default_person);
}
//output
Person { name: "ohBug", age: 20 }
Person { name: "", age: 0 }实例方法&静态方法 #[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}
// 实例方法
impl Person {
    // 如果不是&Self引用类型,则在对象调用此方法后,则对象已经被销毁,因为所有权机制,如果相对其修改则是&mut self
    fn say_my_name(self: &Self) {
        println!("name = {}", self.name)
    }
    // 此参数是上面的语法糖
    fn say_my_age(&self) {
        println!("age = {}", self.age)
    }
}
// 实例方法, 可以多次impl一个struct来实现多个方法
impl Person {
    fn la_bb(&self, msg: &str) -> &str {
        print!("{msg} ~");
        for _ in 0..self.age {
            print!("💩")
        }
        return " shuang";
    }
}
// 关联方法 (静态方法)
impl Person {
    fn cal(x: u32, y: u32) -> u32{
        x + y
    }
}
fn main() {
    let person = Person {
        name: String::from("ohBug"),
        age: 20
    };
    person.say_my_age();
    person.say_my_name();
    let msg = person.la_bb("start ...");
    println!("{msg}");
    // 静态方法则用结构体名调用,与Java不同,Rust中person对象并不能调用cal,只能struct
    // let result = person::cal(2, 3);
    let result = Person::cal(1, 2);
    println!("{result}")
}
// output
age = 20
name = ohBug
start ... ~💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩 shuang
3 
枚举 枚举中的单个枚举被称为枚举类型的变体,不能对具体的单个变体进行impl操作。 #[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}
// 枚举可以包罗万象
#[derive(Debug)]
enum EveryThing {
    Person,
    Circle((i32, i32), i32),
    Open(bool),
    NoName,
    Dog {
        color: (i32, i32, i32),
        name: String,
        age: DogAge,
    },
}
#[derive(Debug)]
enum DogAge {
    OneYears = 1, // 给一个初始值1,后面依次递增
    TwoYears,
    ThreeYears,
}
impl EveryThing {
    // 实例方法   match可有返回值也可没有,如下是对枚举进行解构
    fn say(&self, msg: String) -> String {
        let type_msg = match self {
            Self::Person => "Person",
            Self::Circle((x, y), radius) => &format!("Circle radius = {radius}"),
            Self::Open(flag) => &format!("Open flag = {flag}"),
            Self::Dog { color, name, age } => &format!("Dog name = {name}"),
            _ => "others",   // 匹配不到上面的默认处理
        };
        format!("{type_msg} {msg}")
    }
}
impl EveryThing {
    // 静态方法
    fn view(target: &EveryThing) {
        println!("{:?}", target)
    }
}
fn main() {
    let person = Person {
        name: "ohBug".to_string(),
        age: 20,
    };
    println!("person = {:?}", person);
    let person_everything = EveryThing::Person;
    println!("person_everyThing = {:?}", person_everything);
    let circle_everything = EveryThing::Circle((23, 12), 5);
    println!("circle_everything = {:?}", circle_everything);
    let dog_age = DogAge::ThreeYears;
    println!("dog_age = {:?}", dog_age);
    println!("dog_age = {:?}", dog_age as i32);
    let dog: EveryThing = EveryThing::Dog {
        color: (1, 2, 3),
        name: ("Berber".to_string()),
        age: DogAge::TwoYears,
    };
    println!("dog = {:?}", dog);
    let dog_msg = dog.say("wangwang".to_string());
    println!("dog_msg = {dog_msg}");
    EveryThing::view(&dog);
    // :_ 指定方式可以忽略掉编译器的未使用的警告, 且后续不能够使用此变量
    // 在解构的时候是可以进行重新命名的
    let EveryThing::Dog {color, name: _, age: aaa} = dog else {
        panic!("not a dog");
    };
    println!("color = {:?}", color);
    // 后续不能够使用此变量
    // println!("name = {name}");
    println!("age = {:?}", aaa);
}
// output 
person = Person { name: "ohBug", age: 20 }
person_everyThing = Person
circle_everything = Circle((23, 12), 5)
dog_age = ThreeYears
dog_age = 3
dog = Dog { color: (1, 2, 3), name: "Berber", age: TwoYears }
dog_msg = Dog name = Berber wangwang
Dog { color: (1, 2, 3), name: "Berber", age: TwoYears }
color = (1, 2, 3)
age = TwoYears模式匹配 上面已经写了一些对枚举类型的对象进行解构。除了match可以进行解构外,还可以使用let。 #[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}
fn main() {
    let person = Person  {
        name: "ohBug".to_string(),
        age: 20,
    };
    if let Person {name, age} = person {
        println!("is a person {name}");
    }else {
        println!("not a person");
    }
}
//output 
is a person ohBug 
#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}
fn main() {
    let person = Person  {
        name: "ohBug".to_string(),
        age: 20,
    };
    // ref 是在模式匹配过程中提供⼀个额外的信息,告诉编译器只是需要读取⼀下字段的值⽽已,
    // 不需要获得它的所有权,ref带来的改变就是获取&person.name
    // 还有一个 ref mut 的形式,表示name可变,即可变引用。
    if let Person {ref name, age} = person {
        println!("is a person {name}");
    }else {
        println!("not a person");
    }
    // 如果没有ref,则这里报错
    let person_name = person.name;
    println!("{person_name}")
} 
思考 因为基础类型以及切片类型都是不具有所有权的类型, Rust 默认不会深度拷⻉数据,如果最后let c: String = *b; 成立,则意味着要夺⾛a的所有权。为了不被夺走所有权,则Rust直接阻止了这种方式,也给出了提示,除非所有权类型实现了`Copy` trait 。 fn main() {
    let a: i32 = 3;
    let b: &i32 = &a;
    let c: i32 = *b;
    println!("{c}");
    let a: &str = "3";
    let b: &&str = &a;
    let c: &str = *b;
    println!("{c}");
    let a: String = "3".to_string();
    let b: &String = &a;
    let c: String = *b;
    // error:       ^^ move occurs because `*b` has type `String`
    // , which does not implement the `Copy` trait
    println!("{c}");
}
如下,由上面经验告诉我们解引用会带来所有权的转移,但是在枚举上self和*self效果是一样的,且所有权并不会受到影响,这是因为在枚举match时只是对类型进行了匹配,并不会进行对负载的匹配捕获,因此不存在赋值操作,所以也就没有了所有权问题。进而跟copy trait也就没关系了。其match效果一样是Rust进行了自动的解引用操作。 enum Animal {
    Cat,Dog
}
impl Animal {
    fn is(&self) {
        match self {
            Self::Cat => print!("cat"),
            Self::Dog => print!("dog"),
        }
    }
    fn isa(&self) {
        match *self {
            Self::Cat => print!("cat"),
            Self::Dog => print!("dog"),
        }
    }
}
fn main() {
    let dog = Animal::Dog;
    dog.is();
    dog.isa();
    dog.is();
}
// output
dogdogdog