前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >rust 继承、封装、多态

rust 继承、封装、多态

作者头像
潇洒
发布2023-10-23 14:57:57
5420
发布2023-10-23 14:57:57
举报
文章被收录于专栏:石头岛石头岛

封装(encapsulation)

rust 的封装是基于结构体,而不是对象,结构体就是 rust 的对象,这个和go一样。 默认情况下,结构体只有字段。 注意,结构体自身被标记为 pub,这样其他代码就可以使用这个结构体,但是在结构体内部的字段仍然是私有的!!!! 可以通过实现结构体,来为结构体添加方法,也是和go一样的特性!!

代码语言:javascript
复制
pub struct AveragedCollection {
    list: Vec<i32>,
    average: f64,
}

impl AveragedCollection {
    // 这个 self 是不是有熟悉的感觉,python 中大量使用 self
    pub fn add(&mut self, value: i32) {
        self.list.push(value);
        self.update_average();
    }

    pub fn remove(&mut self) -> Option<i32> {
        let result = self.list.pop();
        match result {
            Some(value) => {
                self.update_average();
                Some(value)
            }
            None => None,
        }
    }

    pub fn average(&self) -> f64 {
        self.average
    }

    fn update_average(&mut self) {
        let total: i32 = self.list.iter().sum();
        self.average = total as f64 / self.list.len() as f64;
    }
}

fn main() {
    let mut average = AveragedCollection {
        list: vec![1, 2, 3],
        average: 3.0,
    };
    // 注意看,这个里用 . 而不是 ::,在rust中对象使用是. 进行调用
    average.add(3);
}

继承(Inheritance)--rust 没有继续机制!!

是一个很多编程语言都提供的机制,一个对象可以定义为继承另一个对象定义中的元素,这使其可以获得父对象的数据和行为,而无需重新定义。 如果一个语言必须有继承才能被称为面向对象语言的话,那么 Rust 就不是面向对象的。因为没有宏则无法定义一个结构体继承父结构体的成员和方法。 其实 go 也是这么干的,这两哥们都不愿意使用继承,而都是通过组合的形式。

rust 如何实现代码复用? Rust 代码中可以使用默认 trait 方法实现来进行有限的共享。

多态(Polymorphism)

Rust 则通过泛型来对不同的可能类型进行抽象,并通过 trait bounds 对这些类型所必须提供的内容施加约束。 这有时被称为 bounded parametric polymorphism。 Rust 选择了一个不同的途径,使用 trait 对象而不是继承。 其实 trait 就是类似于其它语言的接口(Interface),然后以这种形式实现多态。

举个例子:

定义一下Shape的Trait,其中包含一个area方法。 然后,分别为CircleRectangle结构体实现了Shape Trait。 最后,编写了一个print_area函数,它接受一个实现了Shape Trait的参数,并打印出其面积。

通过Trait和动态分发,可以在运行时选择不同的实现,并实现多态的效果。

代码语言:javascript
复制
trait Shape {
    fn area(&self) -> f64;
}

struct Circle {
    radius: f64,
}

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

struct Rectangle {
    width: f64,
    height: f64,
}

impl Shape for Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn print_area(shape: &dyn Shape) {
    println!("Area: {}", shape.area());
}

fn main() {
    let circle = Circle { radius: 1.0 };
    let rectangle = Rectangle { width: 2.0, height: 3.0 };

    print_area(&circle);
    print_area(&rectangle);
}

这个其实和go实现多态的方式是一样的,也是基于实现接口的方式。

总结

Rust 和 go 这两哥们都不支持基于继承的面向对象,都是基于组合的形式,主要是因为rust的设计理念不同。 Rust选择不使用继承来实现多态,而是使用trait和泛型来实现多态性。这是因为Rust的设计目标之一是提供内存安全和无运行时开销的抽象机制。 使用继承来实现多态性的语言,如C++和Java,通常需要在运行时进行动态分派,这需要额外的运行时开销。此外,继承关系还引入了对象的大小和布局的问题。 Rust通过trait和泛型的组合提供了一种更安全、更灵活的多态性实现方式。trait是一种抽象机制,允许定义一组方法的契约,并让类型来实现这些方法。泛型允许在编写代码时引入抽象的类型参数,以便代码可以适用于不同的具体类型。这种静态的泛型多态性在编译时进行类型检查,并且没有运行时开销。 使用trait和泛型实现多态性的优势包括:

  1. 零运行时开销:Rust的trait和泛型在编译时进行静态分派,不需要额外的运行时开销。
  2. 内存安全:Rust的trait和泛型机制保证了类型安全和内存安全,避免了继承层次带来的一些问题,如对象切片的大小和布局问题。
  3. 更灵活的抽象:使用trait和泛型,可以根据需要定义和使用不同的行为集合,而不受固定的继承关系的限制。

综上,Rust选择使用trait和泛型来实现多态性,以提供更安全、更高效、更灵活的抽象机制,并符合Rust的设计目标和哲学。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-06-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 封装(encapsulation)
  • 继承(Inheritance)--rust 没有继续机制!!
  • 多态(Polymorphism)
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档