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 } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话