Skip to main content

OOP 功能

OOP 是程序建模的一种方式.

使用 Trait Object 实现继承和多态

首先定义一个 Trait 表示共通行为. 为了表示实现该 Trait 的对象, 我们需要使用 Trait Object 表示, 即一种特定对象的指针表达.

比如:

// 1. 定义 Trait Draw
pub trait Draw {
fn draw(&self);
}

// Trait Object 表示
pub struct Screen {
pub components: Vec<Box<dyn Draw>>,
}

// 泛型约束表示
pub struct Screen<T: Draw> {
pub components: Vec<T>,
}

// 泛型约束表示的缺点是无法像 Trait Object 那样在运行时自由放入任意的实现对象, 泛型约束只能在编译时替代.
impl<T> Screen<T>
where
T: Draw,
{
pub fn run(&self) {
for component in self.components.iter() {
component.draw();
}
}
}

// Draw 的实现类型
pub struct Button {
pub width: u32,
pub height: u32,
pub label: String,
}

impl Draw for Button {
fn draw(&self) {
// code to actually draw a button
}
}

通过 Box<dyn T> (Trait Object) 表示的好处是可以通过 Rust 编译时检查传入的类型是否实现了协议.

但 Trait Object 的一个缺点是: 它进行的是动态派发,类似其它语言中的 vtable 利用, 动态派发时编译器会在编译时生成一些代码, 这些代码在运行时确定方法的调用地址. 和静态派发比性能更低, Rust 在运行时通过 Trait Object 中的指针来确定方法的调用, 有一个查找的过程, 因此会有性能开销. 且动态派发时编译器无法对该部分代码进行内联优化.

Trait Object 的好处时代码的灵活性高.