struct Vector {
data: [f32; 2]
}
impl Vector {
//many methods
}
现在我想创建一个 Normal
,它的行为几乎与 Vector
完全一样,但我需要区分类型。因为例如变换法线不同于变换矢量。例如,您需要使用转置(逆)矩阵对其进行转换。
现在我可以这样做:
struct Normal {
v: Vector
}
然后重新实现所有的功能
impl Normal {
fn dot(self, other: Normal) -> f32 {
Vector::dot(self.v, other.v)
}
....
}
我想我也可以用 PhantomData
来做
struct VectorType;
struct NormalType;
struct PointType;
struct Vector<T = VectorType> {
data: [f32; 2],
_type: PhantomData<T>,
}
type Normal = Vector<NormalType>;
但是我还需要一种方法来实现特定类型的功能。
它应该很容易实现,例如 add
可以为所有内容添加 point + vector
。
或特定于某种类型的功能
impl Vector<NormalType> {..} // Normal specific stuff
不确定我将如何实现子范围的功能。例如,点积可能只对法线和向量有意义,但对点没有意义。
是否可以为特征边界表达 bool 表达式?
trait NormalTrait;
trait VectorTrait;
impl NormalTrait for NormalType {}
impl VectorTrait for VectorType {}
impl<T: PointTrait or VectorTrait> for Vector<T> {
fn dot(self, other: Vector<T>) -> f32 {..}
}
我有什么选择?
最佳答案
你的问题很宽泛,涉及很多话题。但是您的 PhantomData
想法可能是一个很好的解决方案。您可以为不同的泛型类型编写不同的 impl
block 。我在您的代码中添加了一些内容:
struct VectorType;
struct NormalType;
struct PointType;
struct Vector<T = VectorType> {
data: [f32; 2],
_type: PhantomData<T>,
}
type Normal = Vector<NormalType>;
type Point = Vector<PointType>;
// --- above this line is old code --------------------
trait Pointy {}
impl Pointy for VectorType {}
impl Pointy for PointType {}
// implement for all vector types
impl<T> Vector<T> {
fn new() -> Self {
Vector {
data: [0.0, 0.0],
_type: PhantomData,
}
}
}
// impl for 'pointy' vector types
impl<T: Pointy> Vector<T> {
fn add<R>(&mut self, other: Vector<R>) {}
fn transform(&mut self) { /* standard matrix multiplication */ }
}
// impl for normals
impl Vector<NormalType> {
fn transform(&mut self) { /* tranposed inversed matrix stuff */ }
}
fn main() {
let mut n = Normal::new();
let mut p = Point::new();
n.transform();
p.transform();
// n.add(Normal::new()); // ERROR:
// no method named `add` found for type `Vector<NormalType>` in the current scope
p.add(Point::new());
}
Is it possible to express boolean expression for trait bounds?
没有(还没有)。但是在这种情况下您可以解决它,如上所示:您创建一个新特征 (Pointy
) 并为您的“或”条件中的类型实现它。然后你就绑定(bind)了那个特性。
关于rust - 如何在 Rust 中共享功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38185385/