跟着谷歌安卓团队学Rust - 面向对象的核心结构体的详细入门你想要的都在这里

大家好,我是梦兽编程。欢迎回来与梦兽编程一起刷Rust的系列。

这是由 Google 的 Android开发团队的分享Rust课程。本课程涵盖了 Rust 的方方面面,从基本语法到泛型和错误处理等高级主题。

该课程的最新版本可以在 google.github.io/comprehensi...

如果你喜欢看梦兽编程的版本可以订阅跟着谷歌安卓团队学Rust订阅最新内容,梦兽编程也期待大家关注我的个人网站。

加入梦兽编程微信群,公众号回复111即可。

面向对象

当我们谈论面向对象编程时,我们关注的是如何组织代码和数据,以及如何使用这些代码和数据。

面向对象编程将数据和操作数据的代码封装在一起,形成一个称为对象的单元。对象可以具有属性(数据)和方法(操作)。通过创建对象,我们可以模拟现实世界中的事物或概念,并通过对象之间的交互来解决问题。

面向对象编程的核心概念包括封装、继承和多态。

面向对象编程的目标是将复杂的问题分解为简单的对象,并通过对象之间的交互来解决问题。它提供了一种组织和管理代码的有效方式,并且可以提高代码的可读性、可维护性和可重用性。

struct

结构体 (struct),Rust 与 golang 语言类似没有提供class关键词。同样提供了struct,但是在rust中通过结构体 (struct) 和 trait(trait)来实现面向对象的特性。

与c++/c不一样的地方是:

Rust引入了所有权系统和借用检查器,以确保内存安全和避免数据竞争。这导致Rust在编写面向对象代码时需要更多的注意事项,例如处理生命周期和借用规则。

封装

rust 复制代码
struct Circle {
    radius: f64,
}

impl Circle {
    fn new(radius: f64) -> Self {
        Circle { radius }
    }

    fn area(&self) -> f64 {
        std::f64::consts::PI * self.radius * self.radius
    }
}

fn main() {
    let circle = Circle::new(3.0);
    println!("Area of the circle: {}", circle.area());
}

与其他语言一样,rust中的"类"(class)也是拥有方法的功能。只不过rust中需要使用impl再定义一次。你可以这么认为struct定义"类"的属性。impl实现它的方法。这样做的好处是可以开发分离。如果你要在其他语言系统中实现以上代码大概如下:

kotlin 复制代码
// java 已经忘得差不多了不要见怪
class CircleAbstract {
 float radius = 0;
}

class Circle extends CircleAbstract {
  Circle(float radius) {
  this.radius = radius;
 }
 public area() {
  return PI * this.radius * this.radius;
 }
}

如果你有洁癖需要分开两个文件来写的,在其他语言中估计是需要这样实现。这样对比下来是不是感觉rust会相对简单一点?

继承 & 多态

继承是面向对象的第二特性,它允许一个类(称为子类或派生类)从另一个类(称为父类或基类)继承属性和方法。子类可以从父类继承其所有的非私有成员,包括变量和方法。通过继承,子类可以重用父类的代码,并且可以在其基础上进行扩展或修改。

typescript 复制代码
// 这里使用interface是因为多态
interface Animal {
    void makeSound();
}

class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}

class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();

        dog.makeSound();
        cat.makeSound();
    }
}

在java语言中,我们需要使用interface来约束未来class的实现。在rust中只不过把interface改成trait,implements改为for。然后继承的写法上是反过来。

rust 复制代码
trait Animal {
    fn make_sound(&self);
}

struct Dog;

impl Animal for Dog {
    fn make_sound(&self) {
        println!("Woof!");
    }
}

struct Cat;

impl Animal for Cat {
    fn make_sound(&self) {
        println!("Meow!");
    }
}

fn main() {
    let dog = Dog;
    let cat = Cat;

    dog.make_sound();
    cat.make_sound();
}

多态的作用/好处

在强制类型语言中,多态显得非常重要。如果你使用js/php。这个再使用的过程中完全可以忽略,因为javascript万物皆可json,php中万物皆可array。但是再强制类型语言中,不同的类型是不能放在一起,为了解决这个问题引入了多态。还是上面的的例子进行改造。

我们先定义两个结构体DogCat。然后分别定义一个trait接口Pet,分别继承Pet接口。Vec这个暂时可以了解,这个可以理解成Java里面的ArrayList那玩意,后面进入高级的时候会详细再介绍。

rust 复制代码
struct Dog { name: String, age: i8 }
struct Cat { lives: i8 } // No name needed, cats won't respond anyway.

trait Pet {
    fn talk(&self) -> String;
}

impl Pet for Dog {
    fn talk(&self) -> String { format!("Woof, my name is {}!", self.name) }
}

impl Pet for Cat {
    fn talk(&self) -> String { String::from("Miau!") }
}

fn main() {
 // 定义一个可变的数组集合
    let pets: Vec<Box<dyn Pet>> = vec![
        Box::new(Cat { lives: 9 }),
        Box::new(Dog { name: String::from("Fido"), age: 5 }),
    ];
    for pet in pets {
        println!("Hello, who are you? {}", pet.talk());
    }
}

Deriving

在 Rust 中,"Deriving" 是一种自动为结构体或枚举类型实现特定 trait 的机制。通过使用 "derive" 注解,开发人员可以自动为类型实现一些常见的 trait,而不需要手动编写实现代码。

"Deriving" 机制的目的是减少开发人员的重复劳动,使得实现一些常用 trait 的过程更加简单和高效。例如,通过添加 #[derive(Debug)] 注解,Rust 编译器会自动为结构体或枚举类型实现 Debug trait,使得我们可以通过 println! 宏打印出这些类型的调试信息。

除了 Debug trait,Rust 还提供了其他一些可以使用 "derive" 注解自动实现的 trait,如 Clone、Copy、PartialEq、Eq、PartialOrd、Ord 等。这些 trait 在实现某些功能时非常常见,因此通过 "derive" 机制可以大大简化代码编写过程。

需要注意的是,并非所有的 trait 都可以通过 "derive" 机制来自动实现,只有 Rust 标准库中预定义的一些 trait 才支持这种自动实现机制。如果需要实现的 trait 不在预定义的列表中,开发人员仍然需要手动编写实现代码。

rust 复制代码
#[derive(Debug, Clone, 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);
}

比如我们在这个结构体中添加了Clone,Default的能力。我们的p1对象就拥有了default设置默认值的方法,还有clone的方法。

总结

以上就是Rust面向对象的所有内容啦,当然这些这是让你快速入门。如果你想了解关于它是如何实现,内存机制等等比较深入的东西。建议你去看《Rust圣经》。

rexweb.link/category/te...]

  1. 梦兽编程倔强号
  2. 梦兽编程知乎
  3. 梦兽编程bilibili

微信搜索梦兽编程公众号,发送111即可加入交流群与梦兽编程一起交流。

参考资料

[1]

google.github.io/comprehensi...: google.github.io/comprehensi...

[2]

跟着谷歌团队学Rust: rexweb.link/category/te...

[3]

梦兽编程: rexweb.link

本文使用 markdown.com.cn 排版

相关推荐
唐 城17 分钟前
curl 放弃对 Hyper Rust HTTP 后端的支持
开发语言·http·rust
星就前端叭1 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
小林coding2 小时前
阿里云 Java 后端一面,什么难度?
java·后端·mysql·spring·阿里云
AI理性派思考者2 小时前
【保姆教程】手把手教你在Linux系统搭建早期alpha项目cysic的验证者&证明者
后端·github·gpu
从善若水2 小时前
【2024】Merry Christmas!一起用Rust绘制一颗圣诞树吧
开发语言·后端·rust
lqqjuly2 小时前
特殊的“Undefined Reference xxx“编译错误
c语言·c++
机器之心2 小时前
终于等来能塞进手机的文生图模型!十分之一体量,SnapGen实现百分百的效果
人工智能·后端
机器之心2 小时前
首次!大模型自动搜索人工生命,做出AI科学家的Sakana AI又放大招
人工智能·后端
运维&陈同学3 小时前
【模块一】kubernetes容器编排进阶实战之基于velero及minio实现etcd数据备份与恢复
数据库·后端·云原生·容器·kubernetes·etcd·minio·velero
gerrylon0073 小时前
rust学习: 有用的命令
rust