问题描述
我正在实现一个用于练习的快速几何板条箱,我想实现两个结构,Vector
和 Normal
(这是因为标准向量和法线向量映射通过某些变换方式不同).我已经实现了以下特征:
I am implementing a quick geometry crate for practice, and I want to implement two structs, Vector
and Normal
(this is because standard vectors and normal vectors map through certain transformations differently). I've implemented the following trait:
trait Components {
fn new(x: f32, y: f32, z: f32) -> Self;
fn x(&self) -> f32;
fn y(&self) -> f32;
fn z(&self) -> f32;
}
我还想将两个向量和两个法线相加,所以我有如下所示的块:
I'd also like to be add two vectors together, as well as two normals, so I have blocks that look like this:
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
会做同样的事情).除了为 Point
、Vector
和 Normal
写出三个相同的实现之外,还有什么方法可以做到这一点?可能看起来像这样:
And almost the exact same impl
for Normal
s. What I really want is to provide a default Add impl
for every struct that implements Components
, since typically, they all will add the same way (e.g. a third struct called Point
will do the same thing). Is there a way of doing this besides writing out three identical implementations for Point
, Vector
, and Normal
? Something that might look like this:
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
"将自动被适当的类型替换.我想我可以在宏中做到这一点,但这对我来说似乎有点麻烦.
Where "Components
" would automatically get replaced by the appropriate type. I suppose I could do it in a macro, but that seems a little hacky to me.
推荐答案
在 Rust 中,可以定义通用的 impl
,但是有一些重要的限制来自于一致性规则.你想要一个像这样的 impl
:
In Rust, it is possible to define generic impl
s, but there are some important restrictions that result from the coherence rules. You'd like an impl
that goes like this:
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())
}
}
不幸的是,这不能编译:
Unfortunately, this does not compile:
错误:类型参数 T
必须用作某些本地类型的类型参数(例如 MyStruct
);只能为类型参数实现当前 crate 中定义的特征 [E0210]
为什么?假设您的 Components
特性是公开的.现在,另一个 crate 中的类型可以实现 Components
特性.该类型也可能尝试实现 Add
特性.谁的 Add
实现应该获胜,你的包还是其他包的?根据 Rust 当前的一致性规则,另一个 crate 获得此特权.
Why? Suppose your Components
trait were public. Now, a type in another crate could implement the Components
trait. That type might also try to implement the Add
trait. Whose implementation of Add
should win, your crate's or that other crate's? By Rust's current coherence rules, the other crate gets this privilege.
目前,除了重复 impl
之外,唯一的选择是使用宏.Rust 的标准库在很多地方都使用了宏来避免重复 impl
s(特别是对于原始类型),所以你不必觉得脏!:P
For now, the only option, besides repeating the impl
s, is to use a macro. Rust's standard library uses macros in many places to avoid repeating impl
s (especially for the primitive types), so you don't have to feel dirty! :P
这篇关于为自定义特征提供一揽子特征实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!