我有一个主要封装向量的结构:
struct Group<S> {
elements: Vec<S>
}
我还有一个简单的特征,它也适用于其他结构:
trait Solid {
fn intersect(&self, ray: f32) -> f32;
}
我要实现
Solid
对于 Group
,但我希望能够使用 Group
两者都用于 Solid
的相同实现的列表以及 Solid
的混合实现列表.基本上我想同时使用 Group<Box<Solid>>
和 Group<Sphere>
( Sphere
实现 Solid
)。目前我正在使用这样的东西:
impl Solid for Group<Box<Solid>> {
fn intersect(&self, ray: f32) -> f32 {
//do stuff
}
}
impl<S: Solid> Solid for Group<S> {
fn intersect(&self, ray: f32) -> f32 {
//do the same stuff, code copy-pasted from previous impl
}
}
这行得通,但是两次逐行使用相同的代码不能成为惯用的解决方案。我一定遗漏了一些明显的东西吗?
在我的例子中,我测量了两个 trait 实现之间的显着性能差异,所以总是使用
Group<Box<Solid>>
不是一个很好的选择。
最佳答案
为所有 Box<S>
实现你的特征在哪里 S
实现你的特质。然后你可以委托(delegate)给现有的实现:
impl<S: Solid + ?Sized> Solid for Box<S> {
fn intersect(&self, ray: f32) -> f32 {
(**self).intersect(ray)
// Some people prefer this less-ambiguous form
// S::intersect(self, ray)
}
}
您还会发现对引用执行相同操作会很有用:impl<S: Solid + ?Sized> Solid for &'_ S {
fn intersect(&self, ray: f32) -> f32 {
(**self).intersect(ray)
// Some people prefer this less-ambiguous form
// S::intersect(self, ray)
}
}
全部一起:trait Solid {
fn intersect(&self, ray: f32) -> f32;
}
impl<S: Solid + ?Sized> Solid for Box<S> {
fn intersect(&self, ray: f32) -> f32 {
(**self).intersect(ray)
// S::intersect(self, ray)
}
}
impl<S: Solid + ?Sized> Solid for &'_ S {
fn intersect(&self, ray: f32) -> f32 {
(**self).intersect(ray)
// S::intersect(self, ray)
}
}
struct Group<S>(Vec<S>);
impl<S: Solid> Solid for Group<S> {
fn intersect(&self, _ray: f32) -> f32 {
42.42
}
}
struct Point;
impl Solid for Point {
fn intersect(&self, _ray: f32) -> f32 {
100.
}
}
fn main() {
let direct = Group(vec![Point]);
let boxed = Group(vec![Box::new(Point)]);
let pt = Point;
let reference = Group(vec![&pt]);
let mixed: Group<Box<dyn Solid>> = Group(vec![
Box::new(direct),
Box::new(boxed),
Box::new(Point),
Box::new(reference),
]);
mixed.intersect(1.0);
}
?Sized
绑定(bind)允许S
在编译时没有已知的大小。重要的是,这允许您传入 trait 对象,例如 Box<dyn Solid>
或 &dyn Solid
作为类型Solid
没有已知的大小。也可以看看:
关于rust - 特征对象和特征的直接实现者的特征实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63257600/