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

Jan*_*ese 6 traits rust

我有一个结构,主要封装了一个向量:

struct Group<S> {
    elements: Vec<S>
}
Run Code Online (Sandbox Code Playgroud)

我也有一个简单的特征,该特征也可用于其他结构:

trait Solid {
    fn intersect(&self, ray: f32) -> f32;
}
Run Code Online (Sandbox Code Playgroud)

我想实现SolidGroup,但我希望能够使用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
    }
}
Run Code Online (Sandbox Code Playgroud)

这是可行的,但是两次换行相同的代码不是惯用的解决方案。我一定缺少明显的东西吗?

就我而言,我测量了两个特征实现之间的显着性能差异,因此始终使用Group<Box<Solid>>不是一个好选择。

She*_*ter 5

在实现您特质的所有Box<S>地方S实施您的特质。然后,您只需委托给现有实现即可:

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

您还将发现对参考进行相同的操作可能很有用:

impl<'a, S: Solid + ?Sized> Solid for &'a S {
    fn intersect(&self, ray: f32) -> f32 {
        (**self).intersect(ray)
    }
}
Run Code Online (Sandbox Code Playgroud)

全部一起:

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);
}
Run Code Online (Sandbox Code Playgroud)

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


归档时间:

查看次数:

783 次

最近记录:

8 年,1 月 前