Rust DRY traits 和 generics - impl Add 和 Mul 几乎相同
Rust DRY traits and generics - impl Add and Mul nearly identical
我有以下玩具代码,它使用泛型在 3d 向量上实现一些操作,作为 3 个泛型元素的结构。
use std::ops::Add;
use std::ops::Mul;
#[derive(Debug)]
pub struct Vec3<T> {
x: T,
y: T,
z: T,
}
impl<T> Vec3<T> {
pub fn new(x: T, y: T, z: T) -> Vec3<T> {
Vec3 { x, y, z }
}
}
impl<T: Add<Output = T> + Copy> Add<T> for &Vec3<T> {
type Output = Vec3<T>;
fn add(self, other: T) -> Vec3<T> {
Vec3 {
x: self.x + other,
y: self.y + other,
z: self.z + other,
}
}
}
impl<T: Add<Output = T> + Copy> Add<&Vec3<T>> for &Vec3<T> {
type Output = Vec3<T>;
fn add(self, other: &Vec3<T>) -> Vec3<T> {
Vec3 {
x: self.x + other.x,
y: self.y + other.y,
z: self.z + other.z,
}
}
}
impl<T: Mul<Output = T> + Copy> Mul<T> for &Vec3<T> {
type Output = Vec3<T>;
fn mul(self, other: T) -> Vec3<T> {
Vec3 {
x: self.x * other,
y: self.y * other,
z: self.z * other,
}
}
}
impl<T: Mul<Output = T> + Copy> Mul<&Vec3<T>> for &Vec3<T> {
type Output = Vec3<T>;
fn mul(self, other: &Vec3<T>) -> Vec3<T> {
Vec3 {
x: self.x * other.x,
y: self.y * other.y,
z: self.z * other.z,
}
}
}
很明显,我所做的只是复制并粘贴我的 impl Add
并将 Add
替换为 Mul
并重命名方法名称。
这种轻微的重复让我想到了我的问题 - 生锈中是否有某种东西也概括了这一点?这类似于通用特征或 "meta trait"。在我的场景中,相关的 "meta trait" Op
会有一些方法 op
。然后,不是实现 Add
和 Mul
,而是实现 Op
和 op
将分别取代 +
和 *
运算符.
我探索并发现了超级特性,但我无法想象如何使用它们,因为我希望超越我想象的基本步骤:
trait Op<T>:Add<T>+Mul<T>{
fn op(&self)->T;
}
关于您提出的有关二元运算的更一般特征的问题,该特征将为您创建 Add、Mul 等的含义:据我所知,有 none,我认为您不能 define it yourself 因为孤儿规则。你可以:
- 为二进制操作特征写一个macro
- 使用现有的 Vector3,例如 nalgebra 已经为您实现了这些特征的 Vector3
- 尝试概括num_derive以处理具有多个成员的结构
我有以下玩具代码,它使用泛型在 3d 向量上实现一些操作,作为 3 个泛型元素的结构。
use std::ops::Add;
use std::ops::Mul;
#[derive(Debug)]
pub struct Vec3<T> {
x: T,
y: T,
z: T,
}
impl<T> Vec3<T> {
pub fn new(x: T, y: T, z: T) -> Vec3<T> {
Vec3 { x, y, z }
}
}
impl<T: Add<Output = T> + Copy> Add<T> for &Vec3<T> {
type Output = Vec3<T>;
fn add(self, other: T) -> Vec3<T> {
Vec3 {
x: self.x + other,
y: self.y + other,
z: self.z + other,
}
}
}
impl<T: Add<Output = T> + Copy> Add<&Vec3<T>> for &Vec3<T> {
type Output = Vec3<T>;
fn add(self, other: &Vec3<T>) -> Vec3<T> {
Vec3 {
x: self.x + other.x,
y: self.y + other.y,
z: self.z + other.z,
}
}
}
impl<T: Mul<Output = T> + Copy> Mul<T> for &Vec3<T> {
type Output = Vec3<T>;
fn mul(self, other: T) -> Vec3<T> {
Vec3 {
x: self.x * other,
y: self.y * other,
z: self.z * other,
}
}
}
impl<T: Mul<Output = T> + Copy> Mul<&Vec3<T>> for &Vec3<T> {
type Output = Vec3<T>;
fn mul(self, other: &Vec3<T>) -> Vec3<T> {
Vec3 {
x: self.x * other.x,
y: self.y * other.y,
z: self.z * other.z,
}
}
}
很明显,我所做的只是复制并粘贴我的 impl Add
并将 Add
替换为 Mul
并重命名方法名称。
这种轻微的重复让我想到了我的问题 - 生锈中是否有某种东西也概括了这一点?这类似于通用特征或 "meta trait"。在我的场景中,相关的 "meta trait" Op
会有一些方法 op
。然后,不是实现 Add
和 Mul
,而是实现 Op
和 op
将分别取代 +
和 *
运算符.
我探索并发现了超级特性,但我无法想象如何使用它们,因为我希望超越我想象的基本步骤:
trait Op<T>:Add<T>+Mul<T>{
fn op(&self)->T;
}
关于您提出的有关二元运算的更一般特征的问题,该特征将为您创建 Add、Mul 等的含义:据我所知,有 none,我认为您不能 define it yourself 因为孤儿规则。你可以:
- 为二进制操作特征写一个macro
- 使用现有的 Vector3,例如 nalgebra 已经为您实现了这些特征的 Vector3
- 尝试概括num_derive以处理具有多个成员的结构