跟着谷歌学习Rust:第九课-method/trait/derive

142 阅读3分钟

method

#[derive(Debug)]
struct Race {
    name: String,
    laps: Vec<i32>,
}

impl Race {
    // No receiver, a static method
    //创建一个方法
    fn new(name: &str) -> Self {
        Self { name: String::from(name), laps: Vec::new() }
    }

    // Exclusive borrowed read-write access to self
    fn add_lap(&mut self, lap: i32) {
        self.laps.push(lap);
    }

    // Shared and read-only borrowed access to self
    fn print_laps(&self) {
        println!("Recorded {} laps for {}:", self.laps.len(), self.name);
        for (idx, lap) in self.laps.iter().enumerate() {
            println!("Lap {idx}: {lap} sec");
        }
    }

    // Exclusive ownership of self
    fn finish(self) {
        let total: i32 = self.laps.iter().sum();
        println!("Race {} is finished, total lap time: {}", self.name, total);
    }
}

fn main() {
    let mut race = Race::new("Monaco Grand Prix");
    race.add_lap(70);
    race.add_lap(68);
    race.print_laps();
    race.add_lap(71);
    race.print_laps();
    race.finish();
    // race.add_lap(42);
}

方法是各个语言中都存在的实现方式,在Rust中实现方法通过fn实现,但是Rust的方法有一些特别之处。

  • 方法的第一个参数必须为self!!!(必须的一个点,如果第一个参数不是self那么就是一个关联函数了)
  • 方法的调用通过.的方式,即race.new();如果是关联函数则通过::的方式,即Race::new()(一开始接触Rust傻傻分不清为什么有的是通过.一些通过::调用);
  • 方法的第一个参数为&selt:【代表方法借用对象但是不可修改对象属性】
  • 方法的第一个参数为&mut self:【代表方法借用对象可以修改对象的属性】
  • 方法的第一个参数为self:【代表方法直接获取对象的所有权,但是不能修改对象,方法执行结束对象将被释放】
  • 方法的第一个参数为mut selft:【代表方法直接获取对象的所有权,可以修改对象,方法执行结束对象将被释放】

trait

//创建一个Dog构造函数
struct Dog {
    name: String,
    age: i8,
}
//创建一个构造函数Cat
struct Cat {
    lives: i8,
}

//实现一个特征Pet,实现了两个方法talk和greet
trait Pet {
    fn talk(&self) -> String;

    fn greet(&self) {
        println!("Oh you're a cutie! What's your name? {}", self.talk());
    }
}

//为Dog构造函数实现Pet的特征
impl Pet for Dog {
    fn talk(&self) -> String {
        format!("Woof, my name is {}!", self.name)
    }
}
//为Cat构造函数实现Pet的特征
impl Pet for Cat {
    fn talk(&self) -> String {
        String::from("Miau!")
    }
}

fn main() {
    let captain_floof = Cat { lives: 9 };
    let fido = Dog { name: String::from("Fido"), age: 5 };

    captain_floof.greet();
    fido.greet();
}

trait在Rust中叫做特征,说直白点就是接口(也搞不懂为啥不用接口,其它的语言都是用接口来实现通用的抽象方法,Rust自创了一套)。就是类似Java中的Interface。作用都是一样的抽象通用的方法,用户只要关心接口即可,不需要关心具体的实现。

derive

#[derive(Debug, Clone, Default)]//实现Debug、Clone、Default三个特征,则Rust会自动为Player构造函数实现三个特征的方法,类似Java中Interface接口的default方法
struct Player {
    name: String,
    strength: u8,
    hit_points: u8,
}

fn main() {
    let p1 = Player::default(); // Default trait adds `default` constructor.
    let mut p2 = p1.clone(); // Clone trait adds `clone` method.
    p2.name = String::from("EldurScrollz");
    // Debug trait adds support for printing with `{:?}`.
    println!("{:?} vs. {:?}", p1, p2);
}

derive在Rust中的角色是工具型,即会自动为构造函数实现特征的默认方法,类似Java中Interface接口中default的方法。

trait Clone {
    fn clone() {
        //todo clone的实现
    }
}

#[derive(Clone)]
struct Player {
    
}
//以下代码是上面的代码的具体实现
impl Clone for Player {
    //该代码是derive的具体实现,Rust通过derive自动实现了

}

引用

google.github.io/comprehensi…