使用特征和泛型重载类似行为

Overloading like behavior using traits and generics

我有一个表示 16 位地址的简单结构:

pub struct Address(u16);

现在我想定义一个方法,它允许我们检查一个地址是否在给定的范围内。此方法接受对另一个地址的引用或 u16 值。此外,我希望能够像这样调用:

let addr = Address{ 0x3fec };

let a1 = Address{ 0x3f00 };
let a2 = Address{ 0x4000 };

if addr.between(&a1, &a2) {
    println!("{} lays between {} and {}!", addr, a1, a2);
}

if addr.between(0x3f00, 0x4000) {
    println!("{} lays between {} and {}!", addr, a1, a2);
}

我是一个完全的 Rust 初学者,在 Into、From、Borrow、AsRef、Generics 和 Traits 的丛林中有点迷路了。我将如何实施这种行为?第二种情况似乎是一个特殊问题,因为 0x3fff 实际上是一个整数而不是无符号 16 位值。

是否可以通过为同一类型实现通用特征来模仿这种行为?

您可以在您的类型上实现 From<u16>,并使用通用参数来接受任何可以转换为 Address 的内容,方法是为 Into<Address> 添加特征绑定(Into gets automatically implemented as soon as you have an implementation for From).

请注意,我制作了 Address 类型 Copy 因为它只包含一个 u16,这样您就不必费心参考。


#[derive(Clone, Copy, Debug)]
pub struct Address(u16);

impl From<u16> for Address {
    fn from(addr: u16) -> Self {
        Self(addr)
    }
}

impl Address {
    pub fn between<T, U>(self, lower: T, upper: U) -> bool
    where
        T: Into<Address>,
        U: Into<Address>,
    {
        let lower = lower.into();
        let upper = upper.into();

        lower.0 < self.0 && self.0 < upper.0
    }
}

fn main() {
    let addr = Address(0x3fec);

    let a1 = Address(0x3f00);
    let a2 = Address(0x4000);

    if addr.between(a1, a2) {
        println!("{:?} lays between {:?} and {:?}!", addr, a1, a2);
    }

    if addr.between(0x3f00, 0x4000) {
        println!("{:?} lays between {:?} and {:?}!", addr, a1, a2);
    }
}