Dynamic Types, Rc

  1. I know that in most cases, static types / enum / traits are good. For this particular case, I really do need dynamic types. :frowning:

  2. In this case, I also want it to be "open" (as in I can add structs later), so unfortunately Enum is not a good match.

  3. I am aware of std::any::Any, but I would really like to use Rc.

  4. Question: is there a way to take an object of type Rc and then test to see if it's an R, Rc, Rc, or Rc<...>

I think there is a typo

You could downcast an Rc<dyn Any + 'static> with this function

@RustyYato : Good inferrence! I meant to type

Questino: is there a way to take an object of type Rc<Animal> and then
test to see if it's an Rc<Cat>, Rc<Dog>, Rc<Snake>, ...

1 Like

If this really is what you want, you'll want Animal to be a trait and use the downcast-rs library to get Any-like downcasting.

[macro_use]
extern crate downcast_rs;
use downcast_rs::Downcast;

// To create a trait with downcasting methods, extend `Downcast` and run
// impl_downcast!() on the trait.
trait Base: Downcast {}
impl_downcast!(Base);

// Concrete types implementing Base.
#[derive(Debug)]
struct Foo(u32);
impl Base for Foo {}
#[derive(Debug)]
struct Bar(f64);
impl Base for Bar {}

fn main() {
    // Create a trait object.
    let mut base: Box<Base> = Box::new(Foo(42));

    // Try sequential downcasts.
    if let Some(foo) = base.downcast_ref::<Foo>() {
        assert_eq!(foo.0, 42);
    } else if let Some(bar) = base.downcast_ref::<Bar>() {
        assert_eq!(bar.0, 42.0);
    }

    assert!(base.is::<Foo>());

    // Fail to convert Box<Base> into Box<Bar>.
    let res = base.downcast::<Bar>();
    assert!(res.is_err());
    let base = res.unwrap_err();
    // Convert Box<Base> into Box<Foo>.
    assert_eq!(42, base.downcast::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
}

You can also use a required method on the Animal trait to test what kind of animal it is.

A combination of the two is also possible, E.g. a fourth enum variable that carries &'static str data for custom Animal impls. I don't claim it to be a great solutions, but it's certainly a simple one.

Then there's also mopa.