首页 > 解决方案 > 可以在 Rust 中使用泛型类型的 trait 对象吗?

问题描述

我对如何使用 Rust 的特征对象感到困惑。我有很多模糊的部分理解,但最后我不明白我得到的错误。

我正在尝试在 rust 中实现命令模式,以便在终端周围移动光标。我将其设置为发送实现 Command 特征的特征对象,并具有通用类型的 Command 特征。我不能让这个特征通用吗?

这是我的代码的示例版本:

pub trait Command<T> {
    fn execute(&self, target_instance: &mut T);
}

pub trait Commandable<T> {
    fn send(&mut self, cmd: Box<impl Command<T>>);
}
//-------------------------------------------------------

struct Cursor {
    pos: (isize, isize),
}

impl Cursor {
    fn move_me(&mut self, direction: (isize, isize)) {
        self.pos.0 += direction.0;
        self.pos.1 += direction.1;
    }
}

impl Commandable<Cursor> for Cursor {
    fn send(&mut self, cmd: Box<impl Command<Cursor>>) {
        cmd.execute(self);
    }
}

struct MoveCommand {
    move_direction: (isize, isize),
}

impl MoveCommand {
    pub fn new(move_direction: (isize, isize)) -> Self {
        MoveCommand { move_direction }
    }
}

impl Command<Cursor> for MoveCommand {
    fn execute(&self, cursor: &mut Cursor) {
        cursor.move_me(self.move_direction);
    }
}
//------------------------------------------------------

fn handle_input(input: Option<&str>, target: &mut impl Commandable<Cursor>) {
    let mut cmd: Option<Box<dyn Command<Cursor>>> = None;
    if let Some(key) = input {
        match key {
            "K" => cmd = Some(Box::new(MoveCommand::new( (0, -1) ))),
            "J" => cmd = Some(Box::new(MoveCommand::new( (0, 1) ))),
            "H" => cmd = Some(Box::new(MoveCommand::new( (-1, 0) ))),
            "L" => cmd = Some(Box::new(MoveCommand::new( (1, 0) ))),
            _ => {}
        }
    }
    if let Some(boxed_cmd) = cmd {
        target.send(boxed_cmd); // <-----------------ERROR IS HERE
    }
}

fn main() {
    let mut cursor = Cursor { pos: (0, 0) };
    handle_input(Some("K"), &mut cursor);
}

这是错误:

error[E0277]: the size for values of type `dyn Command<Cursor>` cannot be known at compilation time
  --> src/main.rs:54:21
   |
54 |         target.send(boxed_cmd);
   |                     ^^^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `dyn Command<Cursor>`

标签: rust

解决方案


回答我自己的问题以帮助未来的人们:

我的主要问题是我不明白 和 之间的dyn MyTraitObj区别impl MyTraitObjimpl我交替使用它们,所以一旦我将所有的'交换为dyn',我发布的代码就会编译。

@LeoVen 链接了这个,这解决了我的困惑:当用作方法参数时,trait 和 impl trait 有什么区别?

感谢所有提供帮助的人。


推荐阅读