在Java中,所有对象都从java.lang.Object
继承。在Go中,所有类型/结构都实现空接口interface {}
。 Rust语言中是否有类似的构造?
如果答案是否定的,那是什么让它变得不必要?是因为Rust中的所有实体(模块除外)都可以按类型参数化吗?这是否消除了对所有Rust实体/结构/枚举共享的共同“超类型”或共同特征的需求?
答案 0 :(得分:8)
答案 1 :(得分:2)
我理解它的方式,如果不是完全没必要的话,在Rust中没有必要有基类型。
请注意,参数多态(泛型)的引入已经在java中删除了Object
的大多数用例。
使用Object
,您可以实现可以使用任何类型的Java类型的“通用”方法。另一方面,当你有一个Object
时,你无法用它做什么......你必须把它强制转换回实际的子类型才能使用它。
例如,旧的非通用版本的java集合与Object
一起使用,这意味着你必须像这样工作(样本直接来自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
需要Integer
,get
会返回Integer
。 Object
再也看不到了(虽然由于类型擦除它就在那里,几乎没有隐藏在引擎盖下......)
请注意,Go的主要用途是interface{}
,因为Go没有泛型。 interface{}
的主要使用模式大致相同。当您必须使用多种类型时,可以使用它,并在使用它之前将它(although in a safer way和a 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());
}
}
}