Skip to content

定义结构体并实例化

类似面向对象编程的类语法

rust
struct Student {
    stu_no: i32,
    name: String,
    register_at: String
}

fn main() {
    let tom = Student {
        stu_no: 1001,
        name: String::from("tom"),
        register_at: String::from("2020-01-11"),
    };
    println!("stu_no: {}", tom.stu_no);
    println!("name: {}", tom.name);
    println!("register: {}", tom.register_at);
}

字段初始化的简写语法

类似js对象的简写语法,key和value变量同名可以省略

rust
struct Student {
    stu_no: i32,
    name: String,
    register_at: String
}

fn build_student(id:i32, name:String, register_at:String) -> Student {
    Student {
        stu_no: id, // 不同名是不能缩写语法的
        name,
        register_at,
    }
}

fn main() {
    let name = String::from("jerry");
    let reg_at = String::from("2022-11-21");
    let jerry = build_student(1002, name, reg_at);
    println!("stu_no: {}", jerry.stu_no);
    println!("name: {}", jerry.name);
    println!("register: {}", jerry.register_at);
}

使用结构体更新语法从其他实例创建实例

这个功能类似js的延展符的功能 {...obj1, ...obj2}

rust
struct User {
    id: i32,
    name: String,
    password: String,
    is_actived: bool,
    is_banned: bool,
    is_real_auth: bool,
}
fn main() {
    let tom = User {
        id: 1001,
        name: String::from("tom"),
        password: String::from("123456"),
        is_actived: true,
        is_banned: false,
        is_real_auth: true,
    };
    let jerry = User {
        id: 1002,
        name: String::from("jerry"),
        ..tom // 不会覆盖已有的字段
    };
    println!("jerry.id        :{}", jerry.id);
    println!("jerry.name      :{}", jerry.name);
    println!("jerry.password  :{}", jerry.password);
    println!("jerry.is_actived:{}", jerry.is_actived);
    println!("jerry.is_banned :{}", jerry.is_banned);
    println!("jerry.is_banned :{}", jerry.is_real_auth);
}

定义类元组结构体

rust
// 类似元组一样的结构体
struct IpAddrV4(u8, u8, u8, u8);

impl IpAddrV4 {
    fn to_addr_string(&self) -> String {
        let mut addr_str = String::new();
        addr_str += self.0.to_string().as_str();
        addr_str += ".";
        addr_str += self.1.to_string().as_str();
        addr_str += ".";
        addr_str += self.2.to_string().as_str();
        addr_str += ".";
        addr_str += self.3.to_string().as_str();
        addr_str
    }
}

fn main() {
    let ip = IpAddrV4(192, 168, 11, 255);
    println!("ip: {}", ip.to_addr_string());
}

使用#[derive(Debug)]

  1. 不用管 trait 和 #[derive(debug)] 是什么, 后续都会学
  2. 只需要知道, 在结构体上加上这个就可以使用 println! 这个宏来输出, 以便查看信息
rust
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect = Rectangle {
        width: 10,
        height: 10
    };
    println!("rect width : {}", rect.width);
    println!("rect height: {}", rect.height);

    // 如果没有加上 #[derive] 无法直接输出
    println!("rect: {:?}", rect);

    // 也可以使用dbg宏
    dbg!(rect);
}

实例方法

类似面向对象编程的定义方法

rust
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn get_area(&self) -> u32 {
        self.width * self.height
    }

    // 多个参数  &Self 就是 &Rectangle 的意思,
    // 只不过 Self 是关键字代表当前的 struct
    fn can_hold(&self, other_rect: &Self) -> bool {
        self.width >= other_rect.width && self.height >= other_rect.height
    }
}

fn main() {
    let rect = Rectangle {
        width: 10,
        height: 10
    };
    let rect2 = Rectangle {
        width: 20,
        height: 20,
    };

    println!("rect area: {}", rect.get_area()); // 100
    println!("rect2 area: {}", rect2.get_area()); // 100

    println!("rect2 can hold rect? {}", rect2.can_hold(&rect));
}

关联函数

关联函数只是返回值是 Rectangle, 但第一个参数并不是 &self 所以不能称之为方法

比如之前一直使用的 String::from 就是一个关联函数, 他的第一个参数并不是 &self

rust
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 有些类似面向对象编程的静态方法
    fn square(size: u32) -> Self {
        Self {
            width: size,
            height: size,
        }
    }
}

fn main() {
    let square = Rectangle::square(10);
    dbg!(square);
}

多个 impl

一个结构体可以有多个 impl 块

rust
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

// 放实例方法
impl Rectangle {
    fn get_area(&self) -> u32 {
        self.width * self.height
    }

    fn can_hold(&self, other_rect: &Self) -> bool {
        self.width >= other_rect.width && self.height >= other_rect.height
    }
}

// 放关联函数
impl Rectangle {
    fn square(size: u32) -> Self {
        Self {
            width: size,
            height: size,
        }
    }
}

fn main() {

    let square = Rectangle::square(10);
    dbg!(square);
}

self 和 Self

可以这样理解 self 代表当前实例, 作用类似 Java 的 this 关键字

Self 代表当前 implstruct, 如: impl X Self 就代表 X

Released under the MIT License.