Rust 语言 Any 特征反射一些例子

Rust 语言是静态系统语言,本身不提供反射功能,但是提供了 Any Trait,所有类型(含自定义类型)都自动实现了该特征,所以,我们可以通过它进行一些反射技巧。

获取类型限定名(类型 FullName):std::any::type_name

fn main() {
    println!("{:?}", std::any::type_name::<String>());
    println!("{:?}", std::any::type_name::<i32>());
    println!("{:?}", std::any::type_name::<MyType>());
    println!("{:?}", std::any::type_name::<MyEnum>());
}

struct MyType {
    name: String,
    age: u32,
}

enum MyEnum {
    One,
}

结果:

"alloc::string::String"
"i32"
"hello::MyType"
"hello::MyEnum"

根据变量反射获取类型限定名:std::any::type_name_of_val

#![feature(type_name_of_val)]
use std::any::type_name_of_val;

fn main() {
    let ty = MyType {
        name: "Rustln".to_string(),
        age: 30,
    };

    let num = 30;
    println!("{:?}", type_name_of_val(&ty));
    println!("{:?}", type_name_of_val(&num));
}

struct MyType {
    name: String,
    age: u32,
}

结果:

"hello::MyType"
"i32"

获取类型全局唯一标识符:std::any::TypeId::of

fn main() {
    println!("{:?}", std::any::TypeId::of::<MyType>());
    println!("{:?}", std::any::TypeId::of::<i32>());
}

struct MyType {
    name: String,
    age: u32,
}

结果:

TypeId { t: 8378850550567905954 }
TypeId { t: 3735189839305137790 }

函数接受任意类型参数并打印

use std::{any::Any, fmt::Debug};

fn main() {
    let ty = MyType {
        name: "Rustln".to_string(),
        age: 30,
    };
    let name = String::from("Rustln");

    print_any(&ty);
    print_any(&name);
    print_any(&30);
}

#[derive(Debug)]
struct MyType {
    name: String,
    age: u32,
}

fn print_any<T: Any + Debug>(value: &T) {
    let value_any = value as &dyn Any;

    if let Some(string) = value_any.downcast_ref::<String>() {
        println!("String ({}): {}", string.len(), string);
    } else if let Some(MyType { name, age }) = value_any.downcast_ref::<MyType>() {
        println!("MyType ({}, {})", name, age)
    } else {
        println!("{:?}", value)
    }
}

结果:

MyType (Rustln, 30)
String (6): Rustln
30

判断是否是某类型:std::any::TypeId::is

use std::any::Any;

fn is_string(s: &dyn Any) {
    if s.is::<String>() {
        println!("It's a string!");
    } else {
        println!("Not a string...");
    }
}

fn main() {
    is_string(&0);
    is_string(&"cookie monster".to_string());
}

其他例子

use std::any::{type_name, Any};

fn main() {
    print_if_string(Box::new(Foo {
        age: 30,
        name: String::from("Rustln"),
    }));
}

fn print_if_string(value: Box<dyn Any>) {
    if let Ok(foo) = value.downcast::<Foo>() {
        println!("{:?}", &foo)
    }
}

#[derive(Debug)]
struct Foo {
    name: String,
    age: u32,
}

结果:

Foo { name: "Rustln", age: 30 }

通过 stringify! 宏将表达式输出为字符串

let one_plus_one = stringify!(1 + 1);
assert_eq!(one_plus_one, "1 + 1");
posted @ 2022-04-27 16:28  Rustln  阅读(1355)  评论(0编辑  收藏  举报