【PhysUnits】13 减法操作(sub.rs)

一、源码

这段代码定义了一个自定义的减法 trait MySub 并为实现了特定约束的整数类型实现了这个 trait。

rust 复制代码
use super::basic::Integer;
use core::ops::{Neg, Sub, Add};

pub trait MySub<Rhs = Self> {
    type Output;
    fn my_sub(self, rhs: Rhs) -> Self::Output;
}

impl<I1: Integer, I2: Integer> MySub<I2> for I1
where
    I1: Add<<I2 as Neg>::Output>,
    I2: Neg,
{
    type Output = <I1 as Add<<I2 as Neg>::Output>>::Output;
    
    #[inline]
    fn my_sub(self, rhs: I2) -> Self::Output {
        self + (-rhs)
    }
}

二、导入部分

rust 复制代码
use super::basic::Integer;
use core::ops::{Neg, Sub, Add};
  • 从父模块的 basic 子模块导入 Integer trait

  • 从核心库导入 Neg(取负)、Sub(减法) 和 Add(加法) 这三个操作 trait

三、自定义减法 trait 定义

rust 复制代码
pub trait MySub<Rhs = Self> {
    type Output;
    fn my_sub(self, rhs: Rhs) -> Self::Output;
}
`
+ 定义了一个名为 MySub 的公共 trait

+ 使用泛型参数 Rhs (Right Hand Side 的缩写),默认值为 Self (即实现该 trait 的类型自身)

+ 声明了一个关联类型 Output 表示运算结果的类型

+ 定义了一个方法 my_sub,接收自身和右操作数,返回 Output 类型的结果

### 四、trait 实现
```rust
impl<I1: Integer, I2: Integer> MySub<I2> for I1
where
    I1: Add<<I2 as Neg>::Output>,
    I2: Neg,
{
    type Output = <I1 as Add<<I2 as Neg>::Output>>::Output;
    
    #[inline]
    fn my_sub(self, rhs: I2) -> Self::Output {
        self + (-rhs)
    }
}
  • 为所有实现了 Integer 的类型 I1 和 I2 实现 MySub

  • where 子句约束:

    • I1 必须能加上 I2 的负值 (I1: Add<::Output>)

    • I2 必须能取负 (I2: Neg)

  • 关联类型 Output 定义为 I1 加 I2 的负值的结果类型

  • my_sub 方法实现为 self + (-rhs),即通过加负来实现减

  • #[inline] 提示编译器考虑内联此方法以提高性能

五、关键点解析

  1. 数学原理:
  • 这段代码实现了减法作为加负数的操作 (a - b = a + (-b))

  • 这是数学上减法的标准定义方式

  1. 类型系统:
  • 使用了复杂的类型约束确保类型安全

  • I2 as Neg>::Output 获取 I2 取负后的类型

  • I1 as Add<...>::Output 获取 I1 与某类型相加的结果类型

  1. 设计考虑:
  • 自定义 MySub trait 是为了绕过 Rust 的孤儿规则

  • 保持了与标准库 Sub trait 相似的接口设计

六、使用示例

假设有以下类型:

rust 复制代码
struct MyInt(i32);

impl Integer for MyInt {...}
impl Neg for MyInt {
    type Output = MyInt;
    fn neg(self) -> Self::Output {...}
}
impl Add for MyInt {
    type Output = MyInt;
    fn add(self, rhs: Self) -> Self::Output {...}
}

可以这样使用:

rust 复制代码
let a = MyInt(5);
let b = MyInt(3);
let c = a.my_sub(b);  // 相当于 5 - 3

七、与标准库 Sub 的区别

  1. 避免了孤儿规则问题,因为 MySub 是本地的

  2. 方法名改为 my_sub 而非 sub

  3. 其他方面保持了与标准库 Sub 相同的设计理念

这种模式在需要扩展外部类型功能时很常见,特别是在无法直接实现外部 crate 的 trait 时。

相关推荐
roamingcode5 小时前
我是如何 Vibe Coding,将 AI CLI 工具从 Node.js 迁移到 Rust 并成功发布的
人工智能·rust·node.js·github·claude·github copilot
初恋叫萱萱7 小时前
构建高性能生成式AI应用:基于Rust Axum与蓝耘DeepSeek-V3.2大模型服务的全栈开发实战
开发语言·人工智能·rust
superman超哥2 天前
Serde 性能优化的终极武器
开发语言·rust·编程语言·rust serde·serde性能优化·rust开发工具
sayang_shao2 天前
Rust多线程编程学习笔记
笔记·学习·rust
鸿乃江边鸟2 天前
Spark Datafusion Comet 向量化Rust Native--读数据
rust·spark·native·arrow
硬汉嵌入式2 天前
基于Rust构建的单片机Ariel RTOS,支持Cortex-M、RISC-V 和 Xtensa
单片机·rust·risc-v
低调滴开发3 天前
Tauri开发桌面端服务,配置指定防火墙端口
rust·tauri·桌面端·windows防火墙规则
咚为3 天前
Rust Cell使用与原理
开发语言·网络·rust
咸甜适中4 天前
rust的docx-rs库,自定义docx模版批量生成docx文档(逐行注释)
开发语言·rust·docx·docx-rs
FAFU_kyp4 天前
RISC0_ZERO项目在macOs上生成链上证明避坑
开发语言·后端·学习·macos·rust