有没有办法避免取消对特征对象的引用?

Is there a way to avoid dereferencing with trait objects?

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

示例代码:

/* 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;
}

有什么方法可以让我不必每次都写 &*** 之类的东西吗?

if (**current).is_interacting(&***other) 变为 if current.is_interacting(&***other),因为在这种情况下 Rust 会自动解除引用。

一样,as_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;
}

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

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

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

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

您通过 启用此功能:

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

这是您在特征定义附近添加的一次性代码,使调用站点更简洁。