有没有办法避免使用特征对象解除引用?

时间:2017-07-18 07:10:07

标签: function parameters rust traits dereference

我遇到了一个我认为最适合使用特征对象的问题。虽然我设法使其工作,但它看起来要复杂得多,所以我想知道是否有更优化的方式来使用特征对象。

示例代码:

actualOutput

每次我想使用实际对象时,有没有办法写zlib.inflate之类的内容?

zlib.inflate变为/* This takes a slice of objects implementing trait and compares each of them with all other objects in the slice, if they interact with each other both objects should call a certain function with the other object as a parameter. This is used for a collision system, in case you know of a better way to solve this please let me know. */ fn foo(objects: &mut [Box<Trait>]) { let mut active_objects: Vec<&mut Box<Trait>> = vec!(); for current in objects.iter_mut() { for other in active_objects.iter_mut() { if (**current).is_interacting(&***other) { current.boo(&mut ***other); other.boo(&mut **current); } } active_objects.push(current); } } trait Trait { fn boo(&mut self, other: &mut Trait); fn is_interacting(&self, other: & Trait) -> bool; } ,因为在这种情况下Rust会自动取消引用。

3 个答案:

答案 0 :(得分:3)

作为red75prime points outas_mut()可以对Box采用可变引用,这提供了更好的解决方案:

fn foo(objects: &mut [Box<Trait>]) {
    let mut active_objects: Vec<&mut Box<Trait>> = vec!();

    for current in objects.iter_mut() {
        for other in active_objects.iter_mut() {
            let current = current.as_mut();
            let other = other.as_mut();

            if current.is_interacting(other) {
                current.boo(other);
                other.boo(current);
            }
        }

        active_objects.push(current);
    }
}

trait Trait {
    fn boo(&mut self, other: &mut Trait);

    fn is_interacting(&self, other: &Trait) -> bool;
}

答案 1 :(得分:2)

没有必要在Box向量中保留对active_objects个对象的引用。这应该工作并消除大部分解除引用:

fn foo(objects: &mut [Box<Trait>]) {
    let mut active_objects: Vec<&mut Trait> = vec!();

    for current in objects.iter_mut() {
        let current = current.as_mut();
        for other in active_objects.iter_mut() {
            if current.is_interacting(*other) {
                current.boo(*other);
                other.boo(current);
            }
        }

        active_objects.push(current);
    }
}

答案 2 :(得分:1)

您可以删除代码中的所有解除引用:

fn foo(objects: &mut [Box<Trait>]) {
    let mut active_objects: Vec<&mut Box<Trait>> = vec![];

    for current in objects.iter_mut() {
        for other in active_objects.iter_mut() {
            if current.is_interacting(other) {
                current.boo(other);
                other.boo(current);
            }
        }

        active_objects.push(current);
    }
}

您可以implementing the trait itself for references and boxes to the type启用此功能:

impl<'a, T> Trait for &'a mut T
where
    T: Trait + ?Sized,
{
    fn boo(&mut self, other: &mut Trait) {
        (**self).boo(other)
    }

    fn is_interacting(&self, other: &Trait) -> bool {
        (**self).is_interacting(other)
    }
}

impl<T> Trait for Box<T>
where
    T: Trait + ?Sized,
{
    fn boo(&mut self, other: &mut Trait) {
        (**self).boo(other)
    }

    fn is_interacting(&self, other: &Trait) -> bool {
        (**self).is_interacting(other)
    }
}

这是您在特征定义附近添加的一次性代码,使呼叫网站更加清晰。