You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中能否创建与原生类型行为一致但不可混用的新类型?

如何在Rust中创建类型安全的"新类型"并继承基础类型特性

问题描述

在Rust中,若定义如下类型别名:

pub type UserID = usize;
pub type UserScore = f32;

pub type ItemID = usize;
pub type ItemScore = f32;

无法避免将ItemID变量传入接收UserID参数的函数。

若改用元组结构体:

pub struct UserScore(f32);
pub struct ItemScore(f32);

虽可避免类型混用,但无法直接对两个UserScore变量执行加法等操作,需手动实现Add trait。

请问是否存在方法创建类原生结构体,继承基础类型全部特性且不可与其他类型混用?

解决方案

1. 使用derive_more crate快速实现

这是最便捷的方案,derive_more提供了一系列派生宏,能自动为新类型实现常见运算符、转换等trait,无需手动编写重复代码。

首先在Cargo.toml中添加依赖:

[dependencies]
derive_more = "0.99"

然后定义新类型并派生所需trait:

use derive_more::{Add, Sub, Mul, Div, From, Into};

#[derive(Debug, Clone, Copy, Add, Sub, Mul, Div, From, Into)]
pub struct UserScore(f32);

#[derive(Debug, Clone, Copy, Add, Sub, Mul, Div, From, Into)]
pub struct ItemScore(f32);

这样UserScore自动支持加减乘除运算,还能在f32和UserScore之间互相转换,同时严格保证类型安全——ItemScore和UserScore仍是不同类型,无法混用。

2. 手动实现必要trait(无外部依赖)

如果不想引入第三方库,可以手动为新类型派生Rust内置支持的trait,再按需实现运算符trait:

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct UserScore(f32);

// 实现Add trait以支持加法
impl std::ops::Add for UserScore {
    type Output = Self;
    fn add(self, other: Self) -> Self::Output {
        UserScore(self.0 + other.0)
    }
}

// 实现From trait以支持从f32转换为UserScore
impl From<f32> for UserScore {
    fn from(value: f32) -> Self {
        UserScore(value)
    }
}

这种方式需要逐个实现所需特性,但好处是没有外部依赖,适合轻量场景。

3. 自定义宏批量实现trait

如果有多个新类型需要实现相同的trait集合,可通过自定义宏减少重复代码:

macro_rules! numeric_newtype {
    ($name:ident, $inner:ty) => {
        #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
        pub struct $name($inner);

        impl std::ops::Add for $name {
            type Output = Self;
            fn add(self, other: Self) -> Self::Output {
                $name(self.0 + other.0)
            }
        }

        impl From<$inner> for $name {
            fn from(value: $inner) -> Self {
                $name(value)
            }
        }

        // 可根据需求添加Sub、Mul、Div等其他trait实现
    };
}

// 使用宏快速定义新类型
numeric_newtype!(UserScore, f32);
numeric_newtype!(ItemScore, f32);

内容的提问来源于stack exchange,提问作者Du Shiqiao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 16:22:50