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_even
对 u16
和 u32
重复,所以将其作为默认方法移入特征中。
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());
}
编写了一个特征来检查给定数字(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_even
对 u16
和 u32
重复,所以将其作为默认方法移入特征中。
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());
}