假设我想写一段代码,在运行时可以接收共享相同接口的不同类型的解码器,即trait Decoder
。我想得到的Arc<Mutex<dyn Decoder>>
和向下转换到我的特定解码器。大概是这样的:
use std::sync::{Arc, Mutex};
trait Decoder {}
struct SpecificDecoder1;
impl Decoder for SpecificDecoder1 {}
struct SpecificDecoder2;
impl Decoder for SpecificDecoder2 {}
fn main() {
let decoder: Arc<Mutex<dyn Decoder>> = Arc::new(Mutex::new(SpecificDecoder1));
if let Ok(specific_decoder_1) = decoder.downcast::<Mutex<SpecificDecoder1>>() {
} else if let Ok(specific_decoder_2) = decoder.downcast::<Mutex<SpecificDecoder2>>() {
} else {
}
}
Playground
错误:
error[E0599]: no method named `downcast` found for struct `Arc<Mutex<dyn Decoder>>` in the current scope
--> src/main.rs:26:45
|
26 | if let Ok(specific_decoder_1) = decoder.downcast::<Mutex<SpecificDecoder1>>() {
| ^^^^^^^^ method not found in `Arc<Mutex<dyn Decoder>>`
error[E0599]: no method named `downcast` found for struct `Arc<Mutex<dyn Decoder>>` in the current scope
--> src/main.rs:28:52
|
28 | } else if let Ok(specific_decoder_2) = decoder.downcast::<Mutex<SpecificDecoder2>>() {
| ^^^^^^^^ method not found in `Arc<Mutex<dyn Decoder>>`
但是downcast
只有这个实现:
pub fn downcast<T>(self) -> Result<Arc<T>, Arc<dyn Any + 'static + Send + Sync>>
其中T:Any + Send + Sync + 'static,T
必须实现Any
。我想我必须做这样的事情:
impl Any for SpecificDecoder1 {
fn type_id(&self) -> TypeId {
//what to do here? TypeId has no constructors
}
}
还有,这条路对吗?在C++中,我会使用std::shared_ptr
和std::dynamic_pointer_cast<SpecificDecoder1>
等等。这就是我想做的。
2条答案
按热度按时间tvokkenx1#
可以从
Arc<Mutex<dyn Trait>>
向下转换为Arc<Mutex<Type>>
,尽管你会在下面看到它需要一些unsafe
,而且它不是一个很好的工作流程。我鼓励在此之前探索其他途径(以及一般免责声明,向下转换通常是一种代码气味,表明定义不好的抽象)。无论如何,一个关键的部分是,如果
A
和B
兼容,从Arc<A>
到Arc<B>
* 的转换是可能的-这意味着它们具有相同的大小,对齐方式,并符合其他标准,就像做std::mem::transmute
一样(尽管技术上不需要,但相同的Drop
行为是理想的)。如果满足这些条件,则通过Arc::into_raw
和Arc::from_raw
进行转换,中间有一个指针转换。请参阅有关后者的文档以了解更多信息。我们还知道,从
Mutex<dyn Trait>
转换到Mutex<Type>
是 * 安全的 *(如果dyn Trait
是Type
),因为未调整大小的扩展必须具有相同的布局。另一个关键部分:我们需要扩展
Any
trait,因为它提供了一个type_id()
方法来获取dyn Decoder
后面的当前类型。有了这些,我们可以这样做沮丧:
这仍然不理想,因为您必须访问
Mutex
才能看到它包含的内容,但这更多的是一个可能性的演示。h79rfbju2#
我认为你假设了
Arc<dyn Decoder>
(或Arc<Mutex<dyn Decoder>>
)和Arc<dyn Any>
之间的继承关系。我不认为这个假设是正确的- trait对象不会继承。以下几行可以正常工作: