This question already has answers here:
Why doesn't Rust support trait object upcasting?
(3个答案)
去年关闭。
我尝试了以下代码:
我收到以下编译错误:
我声明了两个特征和一个名为
我还没有弄清楚是否有可能。如果是,如何将特征对象
在C++中,出于相同的目的,我将使用类似于
这是一个我可以使用横向转换的情况的示例:我有一个结构,里面有一些数据,这些数据代表一些现实生活中的实体:
此类型的实例可以在代码库的至少两个不同部分中使用。在这两个部分上,我都需要一个名为
有趣的部分是
为什么不将类型分成两个不同的类型?:从技术上讲,从设计上来说, 为什么不使用泛型/静态调度?因为 为什么不使用
然后让
完成此操作后,您就可以将
主要示例展示了各种使用方式:
Rust Playground
如果
(3个答案)
去年关闭。
我尝试了以下代码:
trait TraitA {
fn say_hello(&self) {
self.say_hello_from_a();
}
fn say_hello_from_a(&self);
}
trait TraitB {
fn say_hello(&self) {
self.say_hello_from_b();
}
fn say_hello_from_b(&self);
}
struct MyType {}
impl TraitA for MyType {
fn say_hello_from_a(&self) {
println!("Hello from A");
}
}
impl TraitB for MyType {
fn say_hello_from_b(&self) {
println!("Hello from B");
}
}
fn main() {
let a: Box<dyn TraitA> = Box::new(MyType {});
let b: Box<dyn TraitB>;
a.say_hello();
b = a;
b.say_hello();
}
我收到以下编译错误:
error[E0308]: mismatched types
--> src/main.rs:34:9
|
34 | b = a;
| ^ expected trait `TraitB`, found trait `TraitA`
|
= note: expected struct `std::boxed::Box<dyn TraitB>`
found struct `std::boxed::Box<dyn TraitA>`
我声明了两个特征和一个名为
MyType
的类型,并为MyType
实现了这两个特征。我创建了一个类型为TraitA
的新特征对象MyType
,我将其称为a
。由于a
也实现了TraitB
,因此我认为应该可以将其转换为TraitB
。我还没有弄清楚是否有可能。如果是,如何将特征对象
a
转换为TraitB
?在C++中,出于相同的目的,我将使用类似于
std::dynamic_pointer_cast<TraitB>(a);
的名称。这是一个我可以使用横向转换的情况的示例:我有一个结构,里面有一些数据,这些数据代表一些现实生活中的实体:
struct MyType {
a: i32,
b: i32,
}
此类型的实例可以在代码库的至少两个不同部分中使用。在这两个部分上,我都需要一个名为
get_final_value
的行为。有趣的部分是
get_final_value
的响应方式取决于谁调用它。a
和b
属于同一类,并不是说get_final_value()
使用这两个值来计算结果。 MyType
只是一个示例。在实际情况下,我有不同的结构,它们都以不同的方式实现了这两个特征。 Any
特性?老实说,直到最近我才知道它的存在。我不记得Rust编程语言提到过它。无论如何,似乎您需要了解具体类型,才能从Any
转换为该具体类型,然后再转换为trait对象。 最佳答案
另一个选择是创建一个使用TraitA
和TraitB
作为超特征的特征,并为每种类型提供强制类型转换:
trait TraitC: TraitA + TraitB {
fn as_trait_a(&self) -> &dyn TraitA;
fn as_trait_b(&self) -> &dyn TraitB;
}
然后让
MyType
实现它:impl TraitC for MyType {
fn as_trait_a(&self) -> &dyn TraitA {
self
}
fn as_trait_b(&self) -> &dyn TraitB {
self
}
}
完成此操作后,您就可以将
TraitC
用作Box
,并将您的程序逻辑同时使用TraitA
和TraitB
。主要示例展示了各种使用方式:
fn test_a(a: &TraitA) {
a.say_hello();
}
fn test_b(b: &TraitB) {
b.say_hello();
}
fn main() {
let c: Box<dyn TraitC> = Box::new(MyType {});
TraitA::say_hello(&*c);
TraitB::say_hello(&*c);
c.as_trait_a().say_hello();
c.as_trait_b().say_hello();
test_a(c.as_trait_a());
test_b(c.as_trait_b());
let a: &dyn TraitA = c.as_trait_a();
a.say_hello();
let b: &dyn TraitB = c.as_trait_b();
b.say_hello();
}
Rust Playground
如果
A
和B
确实真正属于在一起,则可以更好地表示这一点,并且仍然可以让您自由使用它们(如果需要)。关于dynamic - 是否可以将特征对象转换到另一个特征对象?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55895583/
10-14 12:44