【问题标题】:Rust trait stateRust 特征状态
【发布时间】:2014-04-08 11:21:40
【问题描述】:

我将从Rust for Rubyist的这个怪物“怪物”代码开始:

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 方法和带有所有参数的基类的接口(@98​​7654324@、strengthcharismaweapon)。我将在 C++ 中使用抽象类做同样的事情。 我可以找到一些丑陋和不直观的方法来解决这个问题,但是有没有减少代码的好方法?我的意思是,保持它的可扩展性和可读性。

【问题讨论】:

    标签: struct rust code-duplication traits


    【解决方案1】:

    另一种有利于组合的方法,如果需要,更容易从中分离实现(例如,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? (推荐后者,很少需要使用~ 堆分配(小)结构。)
    • @dbaupp 实际上在指针方面我还是个菜鸟。你是对的,这是一个小结构。我会修改我的答案。欢迎任何其他建议。
    • 据我所知,我必须自己实现调度......这很有趣,我是 rustnoob 并认为还有一些其他的神秘机制。
    • @IvanIvanov,目前有几个 RFC 提出了某种虚拟调度,结果证明有时需要这种方式来提高空间效率(例如浏览器引擎中的 DOM 树)。所以未来有可能会有某种“神秘机制”:)
    【解决方案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) {}
    }
    

    更新了一个更好的例子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-03
      • 2018-12-05
      • 1970-01-01
      • 2021-06-07
      • 1970-01-01
      • 1970-01-01
      • 2017-05-12
      相关资源
      最近更新 更多