Как реализовать ops :: Mul в структуре, чтобы она работала как с числовыми типами, так и с другой структурой? - PullRequest
2 голосов
/ 05 августа 2020

Я реализовал 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, он будет реализовывать точечный продукт, но если я передаю ему тип basi c numeri c (целое число, f32, целое число без знака, f64), он умножит x, y и z на скалярное значение. Как бы мне это сделать?

1 Ответ

4 голосов
/ 05 августа 2020

Вы имеете в виду что-то подобное?

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;
...