简体   繁体   English

Rust是否具有所有实体“继承”或实现的类型或特征?

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

In Java, all objects inherit from java.lang.Object . 在Java中,所有对象都继承自java.lang.Object In Go, all types/structs implement the empty interface interface {} . 在Go中,所有类型/结构都实现空接口interface {} Is there any similar construct in the Rust language? Rust语言中是否有类似的结构?

If the answer is no, what makes it unnecessary? 如果答案是否定的,那是什么让它变得没必要? Is it because all entities in Rust (except modules) can be parameterized by type? 是因为Rust中的所有实体(模块除外)都可以按类型参数化吗? Does that remove the need for a common "supertype" or common Trait shared by all Rust entities/structs/enums? 这是否消除了对所有Rust实体/结构/枚举共享的共同“超类型”或共同特征的需求?

Yes, there is a trait. 是的,有一个特点。 It is std::any::Any . 它是std::any::Any

From the docs : 来自文档

The Any trait is implemented by all 'static types, and can be used for dynamic typing Any特性由所有'静态类型实现,可用于动态类型

The way I understand it, if not completely unnecessary, it is less necessary in Rust to have a base type. 我理解它的方式,如果不是完全没必要的话,在Rust中没有必要有基类型。

Note that the introduction of parametric polymorphism (generics) has removed most of the use cases for Object also in java. 请注意,参数多态(泛型)的引入已经在java中删除了Object大多数用例。 With Object you can implement a "generic" method that can work with any kind of java type. 使用Object您可以实现可以使用任何类型的Java类型的“通用”方法。 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. 另一方面,当你有一个Object你无法对它做太多的事情......你必须将它强制转换回实际的子类型才能使用它。

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 ): 例如,旧的非泛型版本的Java集合使用了Object ,这意味着您必须像这样工作(样本直接来自Oracle网站上的这篇文章 ):

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). add需要一个Object (所以你可以使用任何类型的集合)。 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. 但是get返回一个Object ,因此你必须根据你(程序员)对你最初在LinkedList中插入的内容的知识将它强制转换回Integer There's very little type safety here. 这里的类型安全性很小。

The new generic version of the same container, since java 1.5, is: 从java 1.5开始,同一容器的新通用版本是:

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 . 现在你有一个Integer列表,所以add需要Integerget返回Integer Object is nowhere to be seen any more (although due to type erasure it's just there, barely hiding under the hood...) Object无处可见(尽管由于类型擦除它就在那里,几乎躲在引擎盖下......)

Note that Go's main use of interface{} stems from the fact that Go does not have generics. 注意,Go对interface{}的主要用途源于Go没有泛型的事实。 The main pattern of use for interface{} is roughly the same. interface{}的主要使用模式大致相同。 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). 考虑到这一点,理论上你可以以相同的方式使用Rust中的Any (在使用之前检查实际类型并转换为它)。 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... 下面的代码适用于rustc 0.13-nightly(2015-01-01),虽然我确信有更好的方法来编写它...

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());
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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