简体   繁体   中英

Does Rust have a type or trait that all entities “inherit” or implement?

In Java, all objects inherit from java.lang.Object . In Go, all types/structs implement the empty interface interface {} . Is there any similar construct in the Rust language?

If the answer is no, what makes it unnecessary? Is it because all entities in Rust (except modules) can be parameterized by type? Does that remove the need for a common "supertype" or common Trait shared by all Rust entities/structs/enums?

Yes, there is a trait. It is std::any::Any .

From the docs :

The Any trait is implemented by all 'static types, and can be used for dynamic typing

The way I understand it, if not completely unnecessary, it is less necessary in Rust to have a base type.

Note that the introduction of parametric polymorphism (generics) has removed most of the use cases for Object also in java. With Object you can implement a "generic" method that can work with any kind of java type. On the other hand, when you have an Object you can't do much with it... You have to cast it back to the actual subtype to use it.

For instance, the old non-generic version of java collections worked with Object s, This means you had to work like this (sample is straight from this post on Oracle's site ):

LinkedList list = new LinkedList();
list.add(new Integer(1));
Integer num = (Integer) list.get(0);

add takes an Object (so you can use the collection with any type). But get returns an Object too, so you have to cast it back to Integer based on the knowledge that you (the programmer) have on what you originally inserted in the LinkedList. There's very little type safety here.

The new generic version of the same container, since java 1.5, is:

LinkedList<Integer> list = new LinkedList<Integer>();
list.add(new Integer(1));
Integer num = list.get(0);

Now you have a list of Integer , so add takes Integer and get returns Integer . Object is nowhere to be seen any more (although due to type erasure it's just there, barely hiding under the hood...)

Note that Go's main use of interface{} stems from the fact that Go does not have generics. The main pattern of use for interface{} is roughly the same. You use it when you have to work with multiple types and you sort-of cast it ( although in a safer way and with a more elegant pattern ) back to a more useful type before using it.

With that in mind, you could theoretically use Any in Rust in the same way (checking actual type and casting to it before using it). It's just that you will likely not find many cases where this might be useful. The code below works on rustc 0.13-nightly (2015-01-01), although I'm sure there are better ways to write it...

use std::any::{Any, AnyRefExt};

// just a couple of random types
struct Foo {
    a: f64
}

enum Bar {
    Baz(int),
    Qux
}

fn main() {
    // create an array of things that could have any type
    let anything = &[&1i as &Any, &Foo{a: 2.} as &Any, &Bar::Qux as &Any];

    // iterate and print only the integer
    for &any in anything.iter() {
        if any.is::<int>() { // check if type is int
            match any.downcast_ref::<int>() { // cast to int
                Some(a) => { println!("{}", *a); }
                None => panic!()
            }
            // or just (shorter version of the match)
            println!("{}", *any.downcast_ref::<int>().unwrap());
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM