【问题标题】:Does Rust have a type or trait that all entities "inherit" or implement?Rust 是否具有所有实体“继承”或实现的类型或特征?
【发布时间】:2014-01-23 20:47:58
【问题描述】:

在 Java 中,所有对象都继承自 java.lang.Object。在 Go 中,所有类型/结构都实现了空接口 interface {}。 Rust 语言中是否有类似的构造?

如果答案是否定的,那是什么让它变得不必要?是因为 Rust 中的所有实体(模块除外)都可以按类型参数化吗?这是否消除了对所有 Rust 实体/结构/枚举共享的通用“超类型”或通用 Trait 的需求?

【问题讨论】:

标签: rust


【解决方案1】:

是的,有一个特点。是std::any::Any

来自the docs

Any trait 由所有 'static 类型实现,可用于动态类型

【讨论】:

  • -0: Any 不是一个通用的基类或超类型或类似的东西。它确实更类似于 Go 的interface{}。但这不是惯用的——几乎总是泛型或其他一些特性应该是你使用的。
  • 另外,与interface{} 或其他示例不同,Any 实际上只是在 libstd 中定义并像impl<T> Any for T 一样实现的特征,即根本不是语言或编译器的基础。 (尽管它确实在内部使用单个编译器内在来获取每种类型的唯一 ID。)
  • 很好的信息 - 谢谢。对于我的第二个问题,基于这些 cmets,Rust 中几乎所有实体的参数化类型似乎确实减轻了对任何常见超类型或超特征的需求。
  • @huon 实际上,我认为Any 确实依赖于编译器对其功能的支持。 Any 提供的 type_id() 方法最终从使用编译器内部接口的 core::intrinsics::type_id 中提取。
  • @penguin359,确实是编译器内部引用:) 我认为我的观点是与类型系统的交互并不特别,它“只是”一个全面的 impl(即使其中的代码界面需要一点魔法)。
【解决方案2】:

按照我的理解,如果不是完全没有必要的话,Rust 中没有基本类型的必要性。

请注意,参数多态性(泛型)的引入已经删除了 Object 的大部分用例,也在 java 中。 使用Object,您可以实现一个“通用”方法,该方法适用于任何类型的java 类型。另一方面,当你有一个 Object 时,你不能用它做很多事情......你必须将它转换回实际的子类型才能使用它。

例如,Java 集合的旧非泛型版本与 Objects 一起使用,这意味着您必须像这样工作(示例直接来自 this post on Oracle's site):

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

add 采用Object(因此您可以使用任何类型的集合)。但是get 也返回一个Object,因此您必须根据您(程序员)对您最初插入到LinkedList 中的内容的了解将其转换回Integer。这里几乎没有类型安全性。

同一个容器的新通用版本,从 java 1.5 开始,是:

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

现在你有一个Integer 的列表,所以add 接受Integerget 返回IntegerObject 已无处可见(尽管由于类型擦除,它就在那里,几乎没有隐藏在引擎盖下......)

请注意,Go 对 interface{} 的主要使用源于 Go 没有泛型这一事实。 interface{} 的主要使用模式大致相同。当您必须使用多种类型并且在使用它之前将其(although in a safer waya more elegant pattern)转换回更有用的类型时,您可以使用它。

考虑到这一点,理论上你可以在 Rust 中以相同的方式使用Any(在使用之前检查实际类型并强制转换)。只是您可能不会发现很多这可能有用的情况。 下面的代码适用于 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());
        }
    }
}

【讨论】:

    猜你喜欢
    • 2019-12-08
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 2015-03-23
    • 1970-01-01
    相关资源
    最近更新 更多