如何在Rust中实现抽象多态/不相交多态?

zpjtge22  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(113)

这是具体的问题。假设我想为数字定义一个Divides trait,其中应该实现一个方法divides来检查两个数字是否存在整除关系。

pub trait Divides {
    fn divides(&self, &other: Self) -> bool;
}

对于整数,这是通过测试余数是否为零来实现的,而对于真实的,除非除数为零,否则整除关系始终成立。我想要的是如下:

trait Integer: Rem {}
trait Real: Div {}
impl Integer for i8 {}
impl Integer for i16 {}
...
impl Integer for i128 {}
...
impl Integer for u128 {}
impl Real for f32 {}
impl Real for f64 {}

impl <T:Integer> Divides for T {
    fn divides(&self, &other: Self) -> bool {
        self % other == 0
    }
}

impl <T:Real> Divides for T {
    fn divides(&self, &other: Self) -> bool {
        self == 0 || other != 0
    }
}

编译器会告诉我“error:特性Divides的冲突实现”。我知道Rust编译器不支持这些东西。对此有什么变通方法吗?

ctehm74n

ctehm74n1#

正如你所说的,rust不支持它,因为理论上,可能有一个类型同时实现IntegerReal,在这种情况下会有冲突。有一些方法可以实现该功能,但它们可能不适合您的需要,并且它们有自己的缺点。我想到了两种方法:
1.你可以有DividesIntegerDividesReal traits。

pub trait DividesInteger {
    fn divides(&self, other: &Self) -> bool;
}
pub trait DividesReal {
    fn divides(&self, other: &Self) -> bool;
}

impl<T> DividesInteger for T where T: Integer {/*...*/}
impl<T> DividesReal for T where T: Real {/*...*/}

1.可以将数值类型 Package 在枚举中。缺点是它需要拳击。

enum Number {
    Integer(Box<dyn Integer>),
    Real(Box<dyn Real>),
}

impl Divides for Number {
    fn divides(&self, other: &Self) -> bool {
        match self {
            Number::Integer(num) => num & other == 0,
            Number::Real(num) => num == 0 || other != 0,
        }
    }
}

当然,这是假设traits需要实现所需的所有操作。
我的建议是,您为每种类型分别实现它。你可以使用宏来实现。Playground

相关问题