2015-09-04 60 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++編碼器,但也適用於此)。