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

anj*_*ruu 4 rust

我采取的做法迅速几何箱子,我想实现两个结构,Vector以及Normal(这是因为标准的矢量和法向矢量地图通过一定的转换不同).我已经实现了以下特征:

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

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

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()] }
  }
}
Run Code Online (Sandbox Code Playgroud)

impl对于Normals 几乎完全相同.我真正想要的是Add impl为每个实现的结构提供一个默认值Components,因为通常它们都将以相同的方式添加(例如,第三个被调用的结构Point将执行相同的操作).是否有这样做除了用于写出三个相同实现的方式Point,VectorNormal?可能看起来像这样的东西:

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())
  }
}
Run Code Online (Sandbox Code Playgroud)

" Components"将自动替换为适当的类型.我想我可以在一个宏观中做到这一点,但这对我来说似乎有点笨拙.

Fra*_*gné 5

在Rust中,可以定义泛型impls,但是一致性规则会产生一些重要的限制.你想要一个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())
  }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不编译:

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

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

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

  • 我不知道确切的计划,但对我来说,如果 trait 是私有的(不是从板条箱中导出的)或者如果 `impl` 可以被标记为私有(这不是现在可能)。 (2认同)