提到通用对象的特征似乎是不可能的

por*_*uod 5 rust

考虑以下简单结构:

struct Monster {
    // ...
}

struct Player {
    // ...
}

struct Missile {
    // ...
    //target: ???,
}
Run Code Online (Sandbox Code Playgroud)

在编写游戏逻辑时,让对象相互引用是很常见的.在上面的例子中,我们有结构Monster,PlayerMissile说明所需的各种交互.

想象一下,我们有以下特点:PositionThink.以上所有结构都实现了Position,除了Missile实现之外的所有结构Think.

首先要注意的是它Missile是一个归航导弹:它存储一个目标,每当游戏更新Missile物体时,它就会将它移向它的目标.

据我所知,不可能Missile在Rust中合理地存储这个目标.

显然,导弹没有自己的目标.它只是想要访问它的Position特性.游戏对象必须通过Rc或共享Gc.但它并不像Missile只能存储Weak<???>具有Position特征的东西的引用.Box<Position>消耗具有该特征的任何对象的手段.A Box<Any>不允许向下转向特征.

制作Missile<T>和存储目标Weak<T>无济于事.怎么Missile<T>存储?在Collection<T>导弹所针对的每种物体中都有一种?游戏对象需要更通用,而可怕的游戏Box<Any>似乎是不可避免的.

我对Rust很新.令我感到困惑的是,这是不可能的.当然,我一定错过了什么?

Ted*_*ego 4

我对 Rust 也很陌生,但这是我发现的。您可以将该std::rc::Rc<T>结构体与 Box 结合使用。要拥有可变的共享引用,您需要将盒装项目包装在std::cell::RefCell.

所以,你的玩家、怪物、导弹的例子将是这样的:

use std::cell::RefCell;
use std::rc::Rc;

trait Position {
    fn position(&mut self);
}

struct Monster;

impl Position for Monster {
    fn position(&mut self) {
        println!("Rawr I am getting the monster's position");
    }
}

struct Player {
    x: i32,
}

impl Position for Player {
    fn position(&mut self) {
        println!("Getting player's position {}", self.x);
        self.x += 1;
    }
}

struct Missile {
    target: Rc<RefCell<Box<Position>>>,
}

fn main() {
    // Create some stuff
    let player = Rc::new(RefCell::new(Box::new(Player{x: 42}) as Box<Position>));
    let monster = Rc::new(RefCell::new(Box::new(Monster) as Box<Position>));

    // Our missile: initial target - monster
    let mut missile = Missile{target: monster};

    // Should be a monster
    missile.target.borrow_mut().position();

    // Redirect missile to player
    missile.target = player.clone();

    // Should be a player
    missile.target.borrow_mut().position();

    // Show that it is in fact a reference to the original player
    player.borrow_mut().position();
}
Run Code Online (Sandbox Code Playgroud)

然而,通常可以设计不需要共享引用的实体系统,这被认为是更惯用的 Rust。如果您的实体系统非常复杂,我建议使用实体组件系统。

编辑:改进了代码和信息,并删除了一些不准确的信息。