【PhysUnits】3 量纲接口实现解析(dimensional.rs)
一、源码
//! Trait definitions for Dimension
//! 物理单位的Trait定义use typenum::Integer;
use super::Dimension;/// Trait marking valid Dimension types
/// 标记有效单位类型的Trait
pub trait Dimensional: Sized {}impl<M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer>Dimensional for Dimension<M, KG, S, A, K, MOL, CD>{
}
二、代码功能
这段代码定义了一个名为 Dimensional 的标记 trait(标记接口),用于标识合法的物理量维度类型。
三、核心组成
1.Trait 定义
pub trait Dimensional: Sized {// 空trait,没有定义任何方法
}
-
这是一个空 trait,仅作为类型标记使用
-
Sized 约束确保实现该 trait 的类型在编译时大小已知
- Trait 实现
impl<M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer>Dimensional for Dimension<M, KG, S, A, K, MOL, CD> {
}
-
为所有合法的 Dimension 类型自动实现该 trait
-
每个类型参数(M/KG/S/A/K/MOL/CD)都必须实现 Integer trait
-
实现体为空,因为这是一个标记 trait
设计目的
- 类型分类
-
将物理量维度类型与其他普通类型区分开
-
提供类型系统的额外安全保障
- 扩展性设计
-
为未来可能添加的默认方法预留空间
-
可以作为泛型约束条件使用
- 编译时检查
-
确保只有合法的维度组合才能被标记
-
防止不合理的类型被当作物理量使用
使用示例
// 定义合法的物理量类型
type Velocity = Dimension<P1, Z0, N1, Z0, Z0, Z0, Z0>;// 使用Dimensional作为约束
fn process_physical_quantity<T: Dimensional>(quantity: T) {// 处理物理量
}let speed = Velocity::new();
process_physical_quantity(speed); // 正常编译struct NotPhysical;
// process_physical_quantity(NotPhysical); // 编译错误
关键特点
-
零运行时开销:纯编译期行为,不影响运行时性能
-
类型安全:通过 trait 系统限制非法类型的使用
-
可扩展性:未来可以添加关联类型或默认方法
-
符合国际单位制:覆盖 SI 全部 7 个基本量纲
与其他部分的关系
这个 trait 是物理单位库的类型系统基础之一,与 Dimension 结构体配合使用,共同确保物理量计算的类型安全性。它为库的其他功能(如单位转换、量纲检查等)提供了基础类型约束能力。
四、补充说明
当前设计考虑
impl<M: Integer, KG: Integer, ..., CD: Integer> Dimensional for Dimension<M, KG, ..., CD>
关键补充说明
- 封装性设计:
-
当前所有Integer约束已内置于Dimension类型内部
-
用户定义单位时无需显式声明Integer约束
-
示例:
// 用户只需这样定义(无需写约束)
type Velocity = Dimension<P1, Z0, N1, Z0, Z0, Z0, Z0>;
- 为常量泛型过渡准备:
-
当前使用typenum的Integer作为类型参数
-
设计已预留向Rust常量泛型迁移的可能性:
// 未来可能迁移为(当常量泛型成熟后)
struct Dimension<const M: i32, const KG: i32, ..., const CD: i32
>(PhantomData<...>);
- 现有Dimensional trait将保持接口兼容性
- 版本兼容保障:
-
无论底层使用typenum还是常量泛型
-
Dimensional trait都将作为稳定接口存在
-
用户代码无需随实现方式改变而修改
实际影响示例
// 现在和未来的使用方式将保持一致
fn calculate<T: Dimensional>(param: T) {// 无论底层如何实现,此函数签名不变
}