2015-09-04 62 views
4

在我正在处理的事情中,我有一个“数据存储”对象和一组可用于该数据存储的操作。我希望能够轻松扩展这组操作并创建数据存储的备用实现。受modifier crate的启发,我尝试采取它的方法,主要是为抽象(存储,操作)对创建一个特征,然后为每个具体对实现它。Rust中的动态调度

不幸的是,我不能完全弄清楚如何将每个具体对实现与抽象设置绑定。这里是一个“最小”版本的我想要做的事:

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); 
          ^~~~~~~~~~~~~~~~~~~~~ 

有人能提出一个更好的方式来做到这一点,还是有办法解决这个错误?

回答

1

我看不到任何保证Weapon有任何TargetAttackStrategy<_> impl。因此,attack_with功能不能保证是完成(这意味着它可能需要的所有可能的类型定义) - 而不像Haskell,Rust不允许创建部分函数。

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