rust 如何在一个结构体上实现ops::穆尔,使其既能处理数值类型,又能处理另一个结构体?

im9ewurl  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(133)

我已经实现了一个Point3D结构:

use std::ops;

# [derive(Debug, PartialEq)]

pub struct Point3D {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

impl ops::Add<&Point3D> for &Point3D {
    type Output = Point3D;
    fn add(self, rhs: &Point3D) -> Point3D {
        Point3D {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
            z: self.z + rhs.z,
        }
    }
}

impl ops::Sub<&Point3D> for &Point3D {
    type Output = Point3D;
    fn sub(self, rhs: &Point3D) -> Point3D {
        Point3D {
            x: self.x - rhs.x,
            y: self.y - rhs.y,
            z: self.z - rhs.z,
        }
    }
}

impl ops::Mul<&Point3D> for &Point3D {
    type Output = f32;
    fn mul(self, rhs: &Point3D) -> f32 {
        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
}

//Scalar impl of ops::Mul here

# [cfg(test)]

mod tests {
    use super::*;
    #[test]
    fn addition_point_3D() {
        let point1 = Point3D {
            x: 1.0,
            y: 2.0,
            z: 3.0,
        };
        let point2 = Point3D {
            x: 4.0,
            y: 5.0,
            z: 6.0,
        };
        let result = &point1 + &point2;
        assert_eq!(
            result,
            Point3D {
                x: 5.0,
                y: 7.0,
                z: 9.0
            },
            "Testing Addition with {:?} and {:?}",
            point1,
            point2
        );
    }

    #[test]
    fn subtraction_point_3D() {
        let point1 = Point3D {
            x: 1.0,
            y: 2.0,
            z: 3.0,
        };
        let point2 = Point3D {
            x: 4.0,
            y: 5.0,
            z: 6.0,
        };
        let result = &point1 - &point2;
        assert_eq!(
            result,
            Point3D {
                x: -3.0,
                y: -3.0,
                z: -3.0
            },
            "Testing Subtraction with {:?} and {:?}",
            point1,
            point2
        );
    }

    #[test]
    fn point3D_point3D_multiplication() {
        let point1 = Point3D {
            x: 1.0,
            y: 2.0,
            z: 3.0,
        };
        let point2 = Point3D {
            x: 4.0,
            y: 5.0,
            z: 6.0,
        };
        let result = &point1 * &point2;
        assert_eq!(
            result, 32.0,
            "Testing Multiplication with {:?} and {:?}",
            point1, point2
        );
    }

    /*
    #[test]
    fn point3D_scalar_multiplication() {
        let point1 = Point3D { x: 1.0, y: 2.0, z: 3.0};
        let scalar = 3.5;
        let result = &point1 * &scalar;
        assert_eq!(result, Point3D { x: 3.5, y: 7.0, z: 10.5 }, "Testing Multiplication with {:?} and {:?}", point1, scalar);
    }
    */
}

我希望在乘法特性中使用泛型,这样如果我传递给它另一个Point3D类,它将实现点积,但如果我传递给它一个基本的数值类型(整数,f32,无符号整数,f64),它将xy,和z乘以标量值。我将如何做到这一点?

n1bvdmb6

n1bvdmb61#

你是说像那样的事吗?

impl ops::Mul<f32> for &Point3D {
    type Output = Point3D;
    fn mul(self, rhs: f32) -> Point3D {
        Point3D {
            x: self.x * rhs,
            y: self.y * rhs,
            z: self.z * rhs
        }
    }
}

这将允许您执行以下操作:

let point = Point3D { x: 1.0, y: 2.0, z: 3.0};
let result = &point * 4.0;
zynd9foi

zynd9foi2#

要对泛型执行此操作,首先需要使Point3D结构体接受泛型,例如

use std::ops::{Mul, Add};

# [derive(Debug, PartialEq)]

pub struct Point3D<T> {
    pub x: T,
    pub y: T,
    pub z: T,
}

Point3D与数值类型相乘的实现将是

impl<T> Mul<T> for &Point3D<T>
    where T: Mul<Output=T> + Copy
{
    type Output = Point3D<T>;
    fn mul(self, rhs: T) -> Self::Output {
        Point3D {
            x: self.x * rhs,
            y: self.y * rhs,
            z: self.z * rhs,
        }
    }
}

我们有where子句,因为我们的泛型T需要实现MulCopyCopy,因为我们需要复制rhs,以便在所有三个乘法中使用。
您的点积实现也需要根据

impl<T> Mul<&Point3D<T>> for &Point3D<T> 
    where T: Mul<Output=T> + Add<Output=T> + Copy
{
    type Output = T;
    fn mul(self, rhs: &Point3D<T>) -> Self::Output {
        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
}

因为我们当然需要能够在这里添加泛型T

相关问题