Rust中的三种多态性——枚举+结构体(下)

0x00 回顾与开篇

多态性(Polymorphism)在很多语言中都存在,比如Java/C#等。有了编程语言的多态性会使我们在工作中更加灵活和方便。当然,Rust也有多态性的特点。在Rust中有三种主要方法来实现多态,我们的目的就是讨论每种方法的优缺点。上一篇文章介绍了Trait的两种方式。今天咱们一起来看最后一种方式——Enum+Struct。

0x01 Enum + Struct

废话不多说,直接上代码。

enum ShapeEnum {
    Rectangle(Rectangle),
    Triangle(Triangle),
    Circle(Circle)
}

struct Rectangle { pub width: f32, pub height: f32 }
struct Triangle { pub side: f32 }
struct Circle { pub radius: f32 }

trait Shape {
    fn perimeter(&self) -> f32;
    fn area(&self) -> f32;
}

impl Shape for ShapeEnum {
    fn perimeter(&self) -> f32 {
        match self {
            ShapeEnum::Rectangle(rect) => rect.perimeter(),
            ShapeEnum::Triangle(tri) => tri.perimeter(),
            ShapeEnum::Circle(circ) => circ.perimeter(),
        }
    }
    fn area(&self) -> f32 {
        match self {
            ShapeEnum::Rectangle(rect) => rect.area(),
            ShapeEnum::Triangle(tri) => tri.area(),
            ShapeEnum::Circle(circ) => circ.area(),
        }
    }
}

impl Shape for Rectangle {
    fn perimeter(&self) -> f32 {
        self.width * 2.0 + self.height * 2.0
    }
    fn area(&self) -> f32 {
        self.width * self.height
    }
}

impl Shape for Triangle {
    fn perimeter(&self) -> f32 {
        self.side * 3.0
    }
    fn area(&self) -> f32 {
        self.side * 0.5 * 3.0_f32.sqrt() / 2.0 * self.side
    }
}

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

这种写法,在我看来应该是比较不错的一种了。但是它有个缺点,每当你需要添加新的变量和方法时,需要在很多地方添加代码。其它为自己的结构体实现 Shapecrate 将无法将它们传递给 ShapeEnum,维护比较麻烦。

0x02 推荐使用一种方式?

在这里,我们通过一个表格来对比下以上三种方式优缺点吧。(表格仅供参考)

内联布局 不浪费内存 混合类型集合 扩展性 易于编写和维护
枚举
Trait泛型
Trait动态
枚举+结构体

上面的表格仅代表个人看法。在工作中,如果变量很小,已知,有限且没有给其它人提供 crate 的需要。我还是比较建议使用枚举。另外,动态调度还是比较推荐使用的,即使它的性能较低,但大多数时候它仍然表现的还是不错的。当然泛型在很多语言中都存在,如果你熟悉了Java/C#等面向对象的语言,我也是比较推荐的。

0x03 小结

我通过3篇文章啰里啰嗦的介绍了Rust中实现多态的3种方式。可能读到这里,有些同学还在纠结我应该使用哪种方式。其实,在我们平时的大多数情况下使用哪一种并不重要,选择自己喜欢的并且适合自己所应用的场景就可以了,并不要被别人的任何言论所束缚,除非你真的是非要挤出那一点性能,我认为Rust的性能已经足够好了。

最近工作比较繁忙,更新有些慢,望大家见谅了!

你可能感兴趣的:(Rust中的三种多态性——枚举+结构体(下))