Rust trait state

3

我将从这个来自Rust for Rubyist的“Monster”代码开始:

trait Monster {
    fn attack(&self);
    fn new() -> Self;
}

struct IndustrialRaverMonkey {
    life: int,
    strength: int,
    charisma: int,
    weapon: int,
}

struct DwarvenAngel {
    life: int,
    strength: int,
    charisma: int,
    weapon: int,
} ...
impl Monster for IndustrialRaverMonkey { ...
impl Monster for DwarvenAngel { ...

我担心代码重复的问题。在Java中,我会创建一个定义attack方法的接口和一个带有所有参数(lifestrengthcharismaweapon)的基类。在C++中,我会使用抽象类来实现同样的功能。

我可以找到一些丑陋和不直观的方法来解决这个问题,但是否有一种好的方法来减少代码?我的意思是,保持可扩展性和可读性。

2个回答

4

另一种方法是注重组合,这样如果需要的话就更容易分离实现(例如,DwarvenAngelCharacteristics 需要一个额外的字段):

trait Monster {
    fn attack(&self);
}

struct Characteristics {
    life: int,
    strength: int,
    charisma: int,
    weapon: int,
}

struct IndustrialRaverMonkey {
    characteristics: Characteristics
}

struct DwarvenAngel {
    characteristics: Characteristics
}

fn same_attack(c: Characteristics) {
    fail!("not implemented")
}

impl Monster for IndustrialRaverMonkey {
    fn attack(&self) {
        same_attack(self.characteristics)
    }
}

impl Monster for DwarvenAngel {
    fn attack(&self) {
        same_attack(self.characteristics)
    }
}

或者,您可以使用枚举来表示您的怪物类型,这与A.B.的回答非常相似:
trait Monster {
    fn attack(&self);
}

struct Characteristics {
    life: int,
    strength: int,
    charisma: int,
    weapon: int,
}

enum Monsters {
    IndustrialRaverMonkey(Characteristics),
    DwarvenAngel(Characteristics),
}

fn same_attack(_: &Characteristics) {
    fail!("not implemented")
}

impl Monster for Monsters {
    fn attack(&self) {
        match *self {
            IndustrialRaverMonkey(ref c) => same_attack(c),
            DwarvenAngel(ref c)          => same_attack(c)
        }
    }
}

出于好奇,为什么在结构体中使用~Characteristics而不是简单的Characteristics?(后者更推荐,很少有必要使用~来堆分配(小型)结构体。) - undefined
@dbaupp 我在指针方面还是个新手。你说得对,那是一个小的结构体。我会修改我的回答。欢迎提出其他建议。 - undefined
根据我的理解,我必须自己实现分发... 这很有趣,我是个 Rust 初学者,原以为有其他神秘的机制。 - undefined
@IvanIvanov,目前有几个RFC提出了一些虚拟调度的方案,这在某些情况下是为了节省空间而需要的(例如浏览器引擎中的DOM树)。因此,未来可能会出现某种“神秘机制” :) - undefined

2
你认为这样的解决方案可行吗?
trait Actor {
    fn attack(&self);
}

enum MonsterId {
    IndustrialRaverMonkey,
    DwarvenAngel
}

struct Monster {
    life: int,
    strength: int
}

impl Monster {
    fn new(id: MonsterId) -> Monster {
        match id {
            IndustrialRaverMonkey => 
            Monster { life: 12, strength: 8 },

            DwarvenAngel => 
            Monster { life: 18, strength: 12 }
        }
    }
}


impl Actor for Monster { 
    fn attack(&self) {}
}

更新了一个更好的例子。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接