Rust运算符重载:让类型更灵活优雅

宫崎骏风-多弗朗明哥-柯拉松

定义

在 Rust 中,运算符重载是一种特性,允许为自定义类型定义运算符的行为。可以为自定义类型定义加法、减法、乘法、除法等运算符的行为

示例

下面是一个使用 + 运算符的例子

rust 复制代码
use std::ops::Add;

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

impl Add for Point {
    type Output = Point;

    fn add(self, other: Point) -> Point {
        Point {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}

fn main() {
    let p1 = Point { x: 1, y: 2 };
    let p2 = Point { x: 3, y: 4 };

    let p3 = p1 + p2;

    println!("{:?}", p3);
}

main() 运行的结果结果为

rust 复制代码
Point { x: 4, y: 6 }

上面代码示例中首先定义了一个 Point 结构体,然后为 Point 结构体实现了 Add trait,这样就可以使用 + 运算符来对 Point 结构体进行加法运算

因为 Add trait 有一个关联类型 Output,这个关联类型定义了加法运算的结果类型。当为自定义类型实现 Add trait 时,这时需要为 Output 类型指定一个具体的类型,也就是 Point 结构体

在 Rust 中,表达式 a + b 实际上是 a.add(b) 的简写形式,也就是对标准库中 std::ops::Add 特型的 add 方法的调用。Rust 的标准数值类型都实现了 std::ops::Add

还有一些类似的特型(trait)覆盖了其他运算符:a * ba.mul(b) 的简写形式,也就是对 std::ops::Mul 特型的 mul 方法的调用,std::ops::Neg 实现了前缀取负运算符 -,等等

汇总表

下面是运算符重载的特型(trait)汇总表

类别 特型 运算符
一元运算符 std::ops::Neg std::ops::Not -x !x
算术运算符 std::ops::Add std::ops::Sub std::ops::Mul std::ops::Div std::ops::Rem x + y x - y x * y x / y x % y
按位运算符 std::ops::BitAnd std::ops::BitOr std::ops::BitXor std::ops::Shl std::ops::Shr x & y x 竖线 y x ^ y x << y x >> y
复合赋值算术运算符 std::ops::AddAssign std::ops::SubAssign std::ops::MulAssign std::ops::DivAssign std::ops::RemAssign x += y x -= y x *= y x /= y x %= y
复合赋值按位运算符 std::ops::BitAndAssign std::ops::BitOrAssign std::ops::BitXorAssign std::ops::ShlAssign std::ops::ShrAssign x &= y x 竖线= y x ^= y x <<= y x >>= y
比较 std::cmp::PartialEq std::cmp::PartialOrd x == yx != y x < yx <= yx > yx >= y
索引 std::ops::Index std::ops::IndexMut x[y]&x[y] x[y] = z&mut x[y]

提示

由于 | 在当前Markdown解析器中预览效果显示的格式有问题,表格中使用中文 竖线 进行了替代

其他运算符

并非所有运算符都可以在 Rust 中重载。从 Rust 1.50 开始,错误检查运算符 ? 仅适用于 Result 值和 Option 值,不过 Rust 也在努力将其扩展到用户定义类型。同样,逻辑运算符 &&|| 仅限于 bool 值。.. 运算符和 ..= 运算符总会创建一个表示范围边界的结构体,& 运算符总是会借用引用,= 运算符总是会移动值或复制值。它们都不能重载

解引用运算符 *val 和用于访问字段和调用方法的点运算符(如 val.fieldval.method())可以用 Deref 特型和 DerefMut 特型进行重载

Rust 不支持重载函数调用运算符 f(x)。当需要一个可调用的值时,通常只需编写一个闭包即可

注意

虽然运算符重载可以让你的代码更加简洁和易读,但是过度使用运算符重载可能会使代码变得难以理解。因此,应该谨慎使用运算符重载

欢迎大家讨论交流,如果喜欢本文章或感觉文章有用,动动你那发财的小手点赞、收藏、关注再走呗 ^_^

微信公众号:草帽Lufei

相关推荐
东风破_6 小时前
danci 2:创建的单词书到底存在哪里?从 Supabase 一路理解 ORM、Drizzle 和 RLS
数据库·后端·node.js
东风破_7 小时前
danci 项目(三):从 JSON 数据到 AI Coding,真实项目里的数据清洗、Prompt 和工程规范
前端·后端·node.js
东风破_7 小时前
danci 项目(一):从需求到架构,一个单词学习系统为什么会这样设计
前端·后端·node.js
蒲公英eric7 小时前
从客户端到服务端:DVWA DOM 型 XSS 模块完整漏洞分析教程
前端·web安全·ai·xss·dvwa·ai安全
单线程_018 小时前
从案例分析 Vue3 Tokenizer+Parser 源码三
前端·javascript·vue.js
顶点多余8 小时前
那些在算法中适合巩固的知识点---1
java·前端·算法
Setsuna_F_Seiei8 小时前
前端转型 Agent 开发 03 之 Agent Tools - 给 Agent 装上手脚
前端·agent·ai编程
jay神8 小时前
【计算机毕业设计】基于SpringBoot的程序教学辅助系统
java·前端·vue.js·spring boot·后端·毕业设计·课程设计
kyriewen11 小时前
我装了30多个Skill,给AI安排了8个岗位
前端·javascript·ai编程
风骏时光牛马11 小时前
大模型落地实践中的技术选型思路与方案对比
前端