gpt4 book ai didi

rust - 如何从特征对象中获取对具体类型的引用?

转载 作者:行者123 更新时间:2023-11-29 08:20:16 27 4
gpt4 key购买 nike

我如何获得 Box<B>&B&Box<B>来自 a此代码中的变量:

trait A {}

struct B;
impl A for B {}

fn main() {
let mut a: Box<dyn A> = Box::new(B);
let b = a as Box<B>;
}

此代码返回错误:

error[E0605]: non-primitive cast: `std::boxed::Box<dyn A>` as `std::boxed::Box<B>`
--> src/main.rs:8:13
|
8 | let b = a as Box<B>;
| ^^^^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait

最佳答案

在 Rust 中有两种方式进行向下转型。第一种是使用 Any .请注意,这 允许您向下转换为确切的原始具体类型。像这样:

use std::any::Any;

trait A {
fn as_any(&self) -> &dyn Any;
}

struct B;

impl A for B {
fn as_any(&self) -> &dyn Any {
self
}
}

fn main() {
let a: Box<dyn A> = Box::new(B);
// The indirection through `as_any` is because using `downcast_ref`
// on `Box<A>` *directly* only lets us downcast back to `&A` again.
// The method ensures we get an `Any` vtable that lets us downcast
// back to the original, concrete type.
let b: &B = match a.as_any().downcast_ref::<B>() {
Some(b) => b,
None => panic!("&a isn't a B!"),
};
}

另一种方法是为基本特征(在本例中为 A )上的每个“目标”实现一个方法,并为每个所需的目标类型实现转换。


等等,为什么我们需要 as_any ?

即使你加上Any作为 A 的要求,它仍然无法正常工作。第一个问题是 ABox<dyn A> 还将实现Any ...意味着当你调用downcast_ref ,您实际上会在对象类型 A 上调用它. Any可以向下转换为调用它的类型,在本例中为A , 所以你只能回退到 &dyn A你已经拥有了。

但是有一个 Any 的实现某处 中的基础类型,对吗?嗯,是的,但你不能得到它。 Rust 不允许您从 &dyn A “交叉转换”至 &dyn Any .

就是as_any是为了;因为它只是在我们的“具体”类型上实现的东西,所以编译器不会混淆它应该调用哪一个。在 &dyn A 上调用它导致它动态分派(dispatch)到具体实现(同样,在本例中为 B::as_any ),它返回一个 &dyn Any使用 Any 的实现对于 B ,这就是我们想要的。

请注意,您可以通过不使用 A 来回避整个问题。 完全。具体来说,以下有效:

fn main() {
let a: Box<dyn Any> = Box::new(B);
let _: &B = match a.downcast_ref::<B>() {
Some(b) => b,
None => panic!("&a isn't a B!")
};
}

但是,这会阻止您使用任何其他 方法; 所有您在这里可以做的就是向下转换为具体类型。

作为潜在兴趣的最后说明,mopa crate 允许您结合 Any 的功能有自己的特点。

关于rust - 如何从特征对象中获取对具体类型的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55031527/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com