在Python中你可以这样做:
if isinstance("hello", basestring):
print "hello is a string"
else:
print "Not a string"
我的问题是可以使用Rust重新创建或模拟这种代码吗?如果可能的话,这种检查在Rust中是必要的还是有用的?
答案 0 :(得分:4)
Rust可以通过Any
提供向下转发的限制:您可以Any
查询具体类型是X
还是Y
。
虽然构造的有用性相当有限; Rust是一种静态类型的语言,所以在大多数情况下你:
trait
仍然,Chris Morgan开发了一个AnyMap
例如存储每种类型的一个值,而不知道所述类型a-priori,然后他用来为HTTP头提供一个类型化接口而不限制头集到一个已知的集合。
答案 1 :(得分:4)
Python是动态类型的。当您编写函数def foo(x):
时,调用者可以选择将任何类型的值作为参数x
。这就是为什么Python有isinstance()
,以便你可以检查它何时重要。
Rust是静态类型的。代码中的任何变量都具有在编译时已知的类型。对于函数参数,您必须明确地编写它:fn foo(x: String) {
。对于局部变量,您可以编写它:let x: String = something();
或将其留给编译器的类型推断,以根据其他信息(这里基于{的返回类型)找出:let x = something();
{1}})。有时候类型推断没有足够的上下文,你必须编写一个显式的类型注释。
如果所有内容都是已知类型,则返回true或false的something()
函数没有意义。所以Rust没有一个。
请注意,特征对象和isinstance
特征可以使用某种形式的动态类型:
所以你可以写:
Any
fn foo(object: &Any) {
if object.is::<String>() {
// ...
}
}
的类型仍然是静态的:它是object
。但它也代表一些其他任意类型的值。您可以使用其他&Any
方法访问该值,例如Any
。
答案 2 :(得分:1)
我认为Rust中最相似的范例是对枚举类型使用match
关键字。例如,在std::net::IpAddr
情况下,您可以使用匹配来决定要处理Ipv4Addr
还是Ipv6Addr
。
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
fn main() {
do_something(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)));
do_something(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)));
}
fn do_something(v: IpAddr) {
match v {
IpAddr::V4(_x) => {
println!("I'm an IPv4 Address!");
}
IpAddr::V6(_x) => {
println!("I'm an IPv6 Address!");
}
}
}
Link to Rust Playground with working example
这具有在所有地方都具有定义明确的类型的优势,这当然是必需的,因为Rust是强类型的。但是,它确实会对您如何安排数据结构产生潜在影响。因此,这种行为必须提前进行计划。