rust upcast and downcast

1
https://blog.csdn.net/wowotuo/article/details/116489754

  

 

所有 trait 的方法是顺序放在一起,并没有区分方法属于哪个 trait,这样也就导致无法进行 upcast,社区内有 RFC 2765 在追踪这个问题,感兴趣的读者可参考,这里就不讨论解决方案了,介绍一种比较通用的解决方案,通过引入一个 AsBase 的 trait 来解决:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
trait Base {
    fn base(&self) {
        println!("base...");
    }
}
trait AsBase {
    fn as_base(&self) -> &dyn Base;
}
// blanket implementation
impl<T: Base> AsBase for T {
    fn as_base(&self) -> &dyn Base {
        self
    }
}
trait Foo: AsBase {
    fn foo(&self) {
        println!("foo..");
    }
}
#[derive(Debug)]
struct MyStruct;
impl Foo for MyStruct {}
impl Base for MyStruct {}
fn main() {
    let s = MyStruct;
    let foo: &dyn Foo = &s;
    foo.foo();
    let base: &dyn Base = foo.as_base();
    base.base();
}

  

 

 

向下转型(downcast)

向下转型是指把一个 trait object 再转为之前的具体类型,Rust 提供了 Any 这个 trait 来实现这个功能。

大多数类型都实现了 Any,只有那些包含非 'static 引用的类型没有实现。通过 type_id 就能够在运行时判断类型,下面看一示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use std::any::Any;
trait Greeting {
    fn greeting(&self) -> &str;
    fn as_any(&self) -> &dyn Any;
}
struct Cat;
impl Greeting for Cat {
    fn greeting(&self) -> &str {
        "Meow!"
    }
    fn as_any(&self) -> &dyn Any {
        self
    }
}
fn main() {
    let cat = Cat;
    let g: &dyn Greeting = &cat;
    println!("greeting {}", g.greeting());
    // &Cat 类型
    let downcast_cat = g.as_any().downcast_ref::<Cat>().unwrap();
    println!("greeting {}", downcast_cat.greeting());
}
 
上面的代码重点在 downcast_ref,其实现为:
 
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
    if self.is::<T>() {
        unsafe { Some(&*(self as *const dyn Any as *const T)) }
    } else {
        None
    }
}

  

 

posted @   CrossPython  阅读(433)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示