我正在为练习实现快速几何箱,我想实现两个结构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;
}
我还想将两个向量加在一起,以及两个法线,所以我有块看起来像这样:
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()] }
}
}
impl
几乎完全相同Normal
。我真正想要的是为每个实现Add impl
的结构提供一个默认的Components
,因为通常它们都会以相同的方式添加(例如,第三个结构称为Point
将执行相同的操作事情)。除了为Point
,Vector
和Normal
写出三个相同的实现之外,还有办法吗?可能看起来像这样的东西:
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
”将自动替换为适当的类型。我想我可以在一个宏中做到这一点,但这对我来说似乎有点笨拙。
答案 0 :(得分: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())
}
}
不幸的是,这不会编译:
错误:类型参数
中实现当前包中定义的特征T
必须用作某些本地类型的类型参数(例如MyStruct<T>
);只能在类型参数[E0210]
为什么呢?假设您的Components
特征是公开的。现在,另一个箱子中的一个类型可以实现Components
特征。该类型也可能尝试实现Add
特征。谁Add
的实施应该获胜,你的箱子还是其他箱子?根据Rust当前的一致性规则,另一个箱子获得了这一特权。
目前,除了重复impl
之外,唯一的选择是使用宏。 Rust的标准库在许多地方使用宏来避免重复impl
(特别是对于原始类型),所以你不必感到肮脏! :P
答案 1 :(得分:4)
目前,宏是唯一的方法。一致性规则可防止多个可能重叠的实现,因此您无法使用通用解决方案。