特征对象和特征的直接实现者的特征实现

时间:2015-10-09 15:11:36

标签: rust traits

我有一个主要封装矢量的结构:

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
    }
}

这样可行,但两次使用相同代码的行不能成为惯用解决方案。我一定错过了一些明显的东西吗?

就我而言,我衡量两种特质实施之间的显着性能差异,因此始终使用Group<Box<Solid>>并不是一个很好的选择。

1 个答案:

答案 0 :(得分:4)

为所有Box<S>实施您的特征S实现您的特质。然后,您只需委托现有的实现:

impl<S: Solid + ?Sized> Solid for Box<S> {
    fn intersect(&self, ray: f32) -> f32 {
        (**self).intersect(ray)
    }
}

您还会发现对引用执行相同操作非常有用:

impl<'a, S: Solid + ?Sized> Solid for &'a S {
    fn intersect(&self, ray: f32) -> f32 {
        (**self).intersect(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)
    }
}

impl<'a, S: Solid + ?Sized> Solid for &'a S {
    fn intersect(&self, ray: f32) -> f32 {
        (**self).intersect(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<Solid>> = Group(vec![
        Box::new(direct),
        Box::new(boxed),
        Box::new(Point),
        Box::new(reference),
    ]);

    mixed.intersect(1.0);
}

?Sized绑定允许S在编译时没有已知的大小。重要的是,这允许您传递特征对象,例如Box<Solid>&Solid,因为类型Solid没有已知大小。