Rust trait 及其默认实现

Rust trait and its default implementation

编写了一个特征来检查给定数字(u16 或 u32)是否为偶数。

v1.0

trait EvenOdd {
    fn is_even(&self) -> bool;
}

impl EvenOdd for u16 {
    fn is_even(&self) -> bool {
        self % 2 == 0
    }
}

impl EvenOdd for u32 {
    fn is_even(&self) -> bool {
        self % 2 == 0
    }
}

fn main() {
    let x: u16 = 11;
    let y: u32 = 44;

    println!("x = {}, y = {}", x.is_even(), y.is_even());
}

这运行良好。但是由于 is_evenu16u32 重复,所以将其作为默认方法移入特征中。

v2.0

trait EvenOdd {
    fn is_even(&self) -> bool {
        self % 2 == 0
    }
}

impl EvenOdd for u16 {
}

impl EvenOdd for u32 {
}

fn main() {
    let x: u16 = 11;
    let y: u32 = 44;

    println!("x = {}, y = {}", x.is_even(), y.is_even());
}

这会产生编译器错误:

error[E0369]: binary operation `%` cannot be applied to type `&Self`
 --> trait_arithmetic_v2.rs:3:9
  |
3 |         self % 2 == 0
  |         ^^^^^^^^
  |
  = note: an implementation of `std::ops::Rem` might be missing for `&Self`

尝试约束 &self 导致编译器错误:

fn is_even<T: std::ops::Rem> (&self: T) -> bool
    self % 2 == 0
}

error: expected one of `)` or `,`, found `:`
 --> trait_arithmetic_v2.rs:2:44
  |
2 |         fn is_even<T: std::ops::Rem> (&self: T) -> bool {
  |                                            ^ expected one of `)` or `,` here

我可以应用约束的唯一方法是更改​​ is_even api.

v3.0

use std::ops::Rem;

trait EvenOdd {
    fn is_even<T: Rem<Output = T> + PartialEq + From<u8>> (&self, other: T) -> bool {
        other % 2.into() == 0.into()
    }
}

并像 x.is_even(x) 那样使用它,这是不自然的。如何修复我的 v2.0?谢谢。

v2.0 中,编译器不知道您尝试应用算术运算的类型,并且 trait EvenOdd: Rem 不起作用,因为 Rem 需要 Self .

此代码有些受限,但适用于您的示例,并且可以正常运行,因为有 impl From<u16> for u32.

的默认实现
use std::ops::Rem;

trait EvenOdd {
    fn is_even(&self) -> bool;
}

impl<T> EvenOdd for T
where
    T: Copy + From<u16> + PartialEq + Rem<Output=T>
{
    fn is_even(&self) -> bool {
        *self % From::from(2u16) == From::from(0u16)
    }
}

fn main() {
    let x: u16 = 11;
    let y: u32 = 44;

    println!("x = {}, y = {}", x.is_even(), y.is_even());
}