我遇到了一个我认为最适合使用特征对象的问题。虽然我设法使其工作,但它看起来要复杂得多,所以我想知道是否有更优化的方式来使用特征对象。
示例代码:
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会自动取消引用。
答案 0 :(得分:3)
作为red75prime points out,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;
}
答案 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)
}
}
这是您在特征定义附近添加的一次性代码,使呼叫网站更加清晰。