首页 文章

为自定义特征提供毯子特征实现

提问于
浏览
4

我正在为练习实现一个快速几何箱,我想实现两个结构, VectorNormal (这是因为标准向量和法向量以不同方式映射某些变换) . 我已经实现了以下特征:

trait Components {
  fn new(x: f32, y: f32, z: f32) -> Self;
  fn x(&self) -> f32;
  fn y(&self) -> f32;
  fn z(&self) -> f32;
}

我还想将两个向量加在一起,以及两个法线,所以我有块看起来像这样:

impl Add<Vector> for Vector {
  type Output = Vector;
  fn add(self, rhs: Vector) -> Vector {
    Vector { vals: [
      self.x() + rhs.x(), 
      self.y() + rhs.y(), 
      self.z() + rhs.z()] }
  }
}

Normal 几乎完全相同 impl . 我真正想要的是为每个实现 Components 的结构提供默认 Add impl ,因为通常它们都会以相同的方式添加(例如,第三个结构称为 Point 将执行相同的操作) . 除了为 PointVectorNormal 写出三个相同的实现之外,有没有办法做到这一点?可能看起来像这样的东西:

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

其中“ Components ”将自动替换为适当的类型 . 我想我可以在一个宏中做到这一点,但这对我来说似乎有些苛刻 .

2 回答

  • 5

    在Rust中,可以定义泛型 impl ,但是一致性规则会产生一些重要的限制 . 你想要一个像这样的 impl

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

    不幸的是,这不编译:

    error:类型参数T必须用作某些本地类型的类型参数(例如MyStruct <T>);只能在当前包中定义的特征为类型参数[E0210]

    为什么?假设你的 Components 特征是公开的 . 现在,另一个箱子中的一个类型可以实现 Components 特征 . 该类型也可能尝试实现 Add 特征 . 谁的实施 Add 应该赢,你的箱子's or that other crate'?根据Rust当前的一致性规则,另一个箱子获得了这一特权 .

    目前,除了重复 impl 之外,唯一的选择是使用宏 . Rust的标准库在许多地方使用宏来避免重复 impl (特别是对于原始类型),所以你不必感到肮脏! :P

  • 4

    目前,宏是唯一的方法 . 一致性规则可防止多个可能重叠的实现,因此您无法使用通用解决方案 .

相关问题