#macro #traits #own #downcast #person #any #personal

no-std mopa

我自己的个性Any:获取具有额外功能的Any

11次发布

使用旧的Rust 2015

0.2.2 2016年4月5日
0.2.1 2016年1月22日
0.2.0 2015年5月13日
0.1.8 2015年4月13日
0.1.4 2015年1月29日

#445Rust模式

Download history 4024/week @ 2024-03-04 3122/week @ 2024-03-11 2830/week @ 2024-03-18 3091/week @ 2024-03-25 3887/week @ 2024-04-01 2542/week @ 2024-04-08 3390/week @ 2024-04-15 2514/week @ 2024-04-22 2138/week @ 2024-04-29 2247/week @ 2024-05-06 2460/week @ 2024-05-13 3039/week @ 2024-05-20 3259/week @ 2024-05-27 3223/week @ 2024-06-03 2616/week @ 2024-06-10 2864/week @ 2024-06-17

12,289 每月下载量
用于 238 个crate(17 直接)

MIT/Apache

21KB
157

mopa 0.2.2

Build Status

MOPA: 我自己的个性Any。 一个宏,用于在您的自定义特质上实现所有Any方法。

你喜欢Any——它将任何'static类型存储为特质对象,然后将其转回原始类型的功能非常方便,实际上无论出于何种错误的原因,你都需要它。但是这还不够。你真正想要的是具有Any功能的自定义特质对象类型。也许你有一个Person特质,你想让你的个人能做各种事情,但你还想能够方便地将人转回其原始类型,对吧?唉,你现在不能写一个像Box<Person + Any>(至少现在不能)。那么你怎么办?放弃吗?不,不!不,不!来吧,MOPA。

曾经有一个非常友好的特质
叫做Person,肩负重任。
    “我需要成为Any
    以转回Benny——
但我不是,所以我猜我只好等着。”

一个可怜的故事,不是吗?尤其是考虑到还有一只熊在追它,打算吃掉它。幸运的是,现在你可以用三个简单步骤将Person mopafy

  1. 像往常一样将mopa crate添加到你的Cargo.toml中,就像crate根一样

    #[macro_use]
    extern crate mopa;
    
  2. Anymopa::Any,而不是std::any::Any)作为Person的超特质;

  3. mopafy!(Person);.

瞧,现在您可以随心所欲地编写 person.is::<Benny>()person.downcast_ref::<Benny>() 等等。简单吧?

顺便说一下,实际上是熊盘上的人。毕竟,在 Person 的盘子上什么也没有。

#[macro_use]
extern crate mopa;

struct Bear {
    // This might be a pretty fat bear.
    fatness: u16,
}

impl Bear {
    fn eat(&mut self, person: Box<Person>) {
        self.fatness = (self.fatness as i16 + person.weight()) as u16;
    }
}

trait Person: mopa::Any {
    fn panic(&self);
    fn yell(&self) { println!("Argh!"); }
    fn sleep(&self);
    fn weight(&self) -> i16;
}

mopafy!(Person);

struct Benny {
    // (Benny is not a superhero. He can’t carry more than 256kg of food at once.)
    kilograms_of_food: u8,
}

impl Person for Benny {
    fn panic(&self) { self.yell() }
    fn sleep(&self) { /* ... */ }
    fn weight(&self) -> i16 {
        // Who’s trying to find out? I’m scared!
        self.yell();
        self.kilograms_of_food as i16 + 60
    }
}

struct Chris;

impl Chris {
    // Normal people wouldn’t be brave enough to hit a bear but Chris might.
    fn hit(&self, bear: &mut Bear) {
        println!("Chris hits the bear! How brave! (Or maybe stupid?)");
        // Meh, boundary conditions, what use are they in examples?
        // Chris clearly hits quite hard. Poor bear.
        bear.fatness -= 1;
    }
}

impl Person for Chris {
    fn panic(&self) { /* ... */ }
    fn sleep(&self) { /* ... */ }
    fn weight(&self) -> i16 { -5 /* antigravity device! cool! */ }
}

fn simulate_simulation(person: Box<Person>, bear: &mut Bear) {
    if person.is::<Benny>() {
        // None of the others do, but Benny knows this particular
        // bear by reputation and he’s *really* going to be worried.
        person.yell()
    }
    // If it happens to be Chris, he’ll hit the bear.
    person.downcast_ref::<Chris>().map(|chris| chris.hit(bear));
    bear.eat(person);
}

fn main() {
    let mut bear = Bear { fatness: 10 };
    simulate_simulation(Box::new(Benny { kilograms_of_food: 5 }), &mut bear);
    simulate_simulation(Box::new(Chris), &mut bear);
}

现在您应该这样做吗?可能不是。对于这个特定的案例,枚举可能是一个更好的解决方案;坦白地说,我相信您几乎只有在生产类似 AnyMap 这样的泛型参数时,才应该向下转型 Any 特质对象(或修改过的特质对象)。如果您控制了所有代码,Any 特质对象可能不是正确的解决方案;它们适用于跨多个库的用户定义类型的情况。但关于目的和适用性的问题仍然是开放的,目前我没有一个很好的用例来展示这种情况。待办事项。

用法

使用 Cargo。 http://crates.io/crates/mopa

作者

Chris Morgan (chris-morgan) 是这个库的主要作者和维护者。

许可协议

这个库以与 Rust 相似的方式分发:双重许可,受 MIT 许可证和 Apache 许可证(版本 2.0)的约束。

有关详细信息,请参阅 LICENSE-APACHE、LICENSE-MIT 和 COPYRIGHT。

无运行时依赖

功能