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 的好处时代码的灵活性高.