rust - Rust 中的动态调度

标签 rust

在我正在做的事情中,我有一个“数据存储”对象和一组可以应用于该数据存储的操作。我希望能够轻松扩展操作集并创建数据存储的替代实现。灵感来自 modifier crate ,我尝试采用它的方法,本质上是为抽象(存储、操作)对创建一个特征,然后为每个具体对实现它。

不幸的是,我不太清楚如何将每个具体对的实现与抽象设置联系起来。这是我正在尝试做的事情的“最小”版本:

use std::fmt::Debug;

trait Target: Debug {}
impl<T: Target + ?Sized> Target for Box<T> {}

trait Weapon: Debug {}
impl<W: Weapon + ?Sized> Weapon for Box<W> {}

trait AttackStrategy<T: Target> {
    fn attack(&self, &T);
}

impl<T: Target, S: AttackStrategy<T> + ?Sized> AttackStrategy<T> for Box<S> {
    fn attack(&self, enemy: &T) {
        &self.attack(enemy);
    }
}

trait Attack {
    fn attack_with<S: AttackStrategy<Self>>(&self, strategy: &S) where Self: Target + Sized {
        strategy.attack(self);
    }
}

impl<T: Target> Attack for T {}

#[derive(Debug)]
struct Zombie(i32);
impl Target for Zombie {}

#[derive(Debug)]
struct Bunny(i32);
impl Target for Bunny {}

#[derive(Debug)]
struct BaseballBat(i32);
impl Weapon for BaseballBat {}

#[derive(Debug)]
struct Knife(i32);
impl Weapon for Knife {}

impl AttackStrategy<Zombie> for BaseballBat {
    fn attack(&self, zed: &Zombie) {
        println!("Attacking {:?} with {:?}! Whack whack whack! Whew. That was close!", zed, self);
    }
}

impl AttackStrategy<Bunny> for BaseballBat {
    fn attack(&self, hopper: &Bunny) {
        println!("Attacking {:?} with {:?}! Swoosh swoosh swoosh! Dang, he got away!", hopper, self);
    }
}

impl AttackStrategy<Zombie> for Knife {
    fn attack(&self, zed: &Zombie) {
        println!("Attacking {:?} with {:?}! Stick stick stick! Oh no! He bit me!", zed, self);
    }
}

impl AttackStrategy<Bunny> for Knife {
    fn attack(&self, hopper: &Bunny) {
        println!("Attacking {:?} with {:?}! Stick stick stick! Yum! Dinner!", hopper, self);
    }
}

#[allow(dead_code)]
fn main() {
    let louisville_slugger = BaseballBat(5);
    let rabbit = Bunny(-1);
    rabbit.attack_with(&louisville_slugger);

    let cleaver: Box<Weapon> = Box::new(Knife(2));
    let brains_seeker = Zombie(17);
    brains_seeker.attack_with(&cleaver);
}

失败并出现错误:

test.rs:75:19: 75:40 error: the trait `AttackStrategy<Zombie>` is not implemented for the type `Weapon` [E0277]
test.rs:75     brains_seeker.attack_with(&cleaver);
                             ^~~~~~~~~~~~~~~~~~~~~

有人可以建议更好的方法或解决此错误的方法吗?

最佳答案

我看不出有任何保证你的 Weapon有一个AttackStrategy<_>对任何 Target 的暗示.因此 attack_with函数不能保证完整(这意味着在它可能采用的所有可能类型上定义)——与 Haskell 不同,Rust 不允许创建部分函数。

使用 component pattern 可能会更好地解决您的具体问题(该文本针对 C++ 编码人员,但也适用于此)。

关于rust - Rust 中的动态调度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32389495/

相关文章:

string - 从 Vec<char> 创建字符串

colors - 使用 SIMD 向量的 RGB 到 YCbCr 会丢失一些数据

rust - &str 字符串和生命周期

python - 将元组的 Rust 向量转换为 C 兼容结构

rust - 尝试 `use` 枚举结果为 "unresolved import"

generics - 当 T 没有实现 Clone 时,为什么不能为泛型 Option<T> 克隆 None?

rust - 为什么在调用一个方法时会借用一个移动的值,该方法使用也调用方法的参数来按值获取 self ?

string - 如果 NUL 终止符不在切片的末尾,如何从以 NUL 终止的字节切片中获取 '&str'?

rust - 当返回使用 StdinLock 的结果时,为什么保留对 stdin 的借用?

rust - 匹配模式中变量的生命周期