-
I know that in most cases, static types / enum / traits are good. For this particular case, I really do need dynamic types.
-
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.
-
I am aware of std::any::Any, but I would really like to use Rc.
-
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.
- This example uses an enum, assuming you know exactly how many kinds of animals will exist at compile-time.
-
This example uses static strings, allowing downstream crates to implement their own
Animal
types.
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.