建设单位到江川区住房和城乡建设局网站,人和机械网站建设,室内设计网站知乎,wordpress 域名米表背景
看rust官方文档,好奇Any和Go的Any是否是一回事,看到下文的一行代码,了解下它的功能
pub trait Any: static {// Required methodfn type_id(self) - TypeId;
}std::any 用于 dynamic typing 或者 type reflection 模拟动态类型的trait。
大多数类型都实现 …背景
看rust官方文档,好奇Any和Go的Any是否是一回事,看到下文的一行代码,了解下它的功能
pub trait Any: 'static {// Required methodfn type_id(self) - TypeId;
}std::any 用于 dynamic typing 或者 type reflection 模拟动态类型的trait。
大多数类型都实现 Any。但是,任何包含非静态引用的类型都不会。
use std::any::Any;fn main() {use std::any::{Any, TypeId};fn is_string(s: dyn Any) - bool {TypeId::of::String() == s.type_id()}assert_eq!(is_string(0), false);assert_eq!(is_string("cookie monster".to_string()), true);
}Any and TypeId
TypeId 代表一个全局唯一类型标识符 Any 本身可以用来获取 TypeId,并且当用作 Trait 对象时具有更多功能(used as a trait object)。
作为 dyn Any(借用的trait对象) 它具有 is 和 downcast_ref 方法,用于测试包含的值是否属于给定类型(is of a given type),并获取对内部值的引用(get a reference to the inner value as a type)。作为 mut dyn Any 有 downcast_mut 方法,用于获取对内部值的可变引用(mutable reference)。 Box 添加向下转换方法,该方法尝试转换为 Box。注意 dyn Any 仅限于测试值是否属于指定的具体类型(alue is of a specified concrete type) 不能用于测试类型是否实现特征(a type implements a trait)。
Smart pointers 和 dyn Any
使用 Any 作为trait对象时要记住的一个行为,尤其是使用 Box 或 Arc 等类型时,只需对值调用 .type_id() 将生成容器的 TypeId(比如Box、Arc) ,而不是底层trait对象(simply calling .type_id() on the value will produce the TypeId of the container, not the underlying trait object)。
可以通过将智能指针转换为 dyn Any 来避免这种情况,这将返回对象的 TypeId。
use std::any::{Any, TypeId};fn main() {let boxed: Boxdyn Any = Box::new(3_i32);let boxed_any: dyn Any = Box::new(3_i32);// 对值调用 .type_id() 将生成容器的 TypeIdlet boxed_id = boxed.type_id();// 将智能指针转换为 dyn Any 来避免这种情况,返回对象的 TypeIdlet boxed_any_id = boxed_any.type_id();// 但是你可能更期待这样let actual_id = (*boxed).type_id();assert_eq!(boxed_id, TypeId::of::Boxdyn Any()); // Boxdyn Anyassert_eq!(boxed_any_id, TypeId::of::Boxi32()); // Boxi32assert_eq!(actual_id, TypeId::of::i32()); // i32
}考虑一种情况,要打印(log out)传递给函数的值。已知道正在处理的值实现 Debug(the value we’re working on implements Debug),但不知道它的具体类型。 同时又希望对某些类型给予特殊处理:在这种情况下,先打印 String 值的长度,再打印它们的值(print out the length of String values prior to their value.)。在编译时不知道值的具体类型,因此我们需要使用运行时反射(runtime reflection)。
use std::fmt::Debug;
use std::any::Any;// 对任何实现了Debug的类型进行Logger打印
fn logT: Any + Debug(value: T) {// 一个值 value 进行类型转换,并将其转换为 dyn Any 类型的引用。// 这种转换允许将一个具体类型的值视为实现了 Any trait 的类型,// 并且可以在运行时进行类型检查和转换// // 【value_any视为一个实现了 Any trait 的类型】let value_any = value as dyn Any;// 【将动态类型转换为具体类型】// downcast_ref 方法来尝试将 dyn Any 引用转换为 String 类型的引用// 它会返回一个 Option,以便在转换失败时处理错误情况match value_any.downcast_ref::String() {Some(as_string) = {println!("String ({}): {}", as_string.len(), as_string)