我尝试了以下代码:
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
实现了这两个特质。我创建了一个名为a
的MyType
类型的新特质对象TraitA
。由于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
强制转换为该具体类型,然后再转换为特征对象。
Any
特性来实现向下转换。 - Sven Marnachget_final_value
中使用它们吗?例如,一种选择是让get_final_value
接受任何实现了第三个 trait 的东西,然后TraitA
和TraitB
都可以公开一个将它们转换为该第三种类型的函数。 - loganfsmythAny
的问题 - 这个代码使用了内部存在于Any中的代码来执行向下转型。Rust仍然不原生支持向下转型,这是一个独立的事情。编写Any的人实际上编写了一些Rust代码来模拟向下转型,因为它不被支持。此外,Rust支持从类型到Trait对象的向上转型(普通指针到胖指针)。至于其他形式的向上转型,比如Trait对象之间的转型,我还没有详细研究过,所以无法给出答案。 - FreelanceConsultantAny
的观点-这使用了存在于Any内部的代码来执行向下转型。Rust仍然不原生支持向下转型,这是一个独立的事情。编写Any的人本质上编写了一些Rust代码来模拟向下转型,因为它不受支持。此外,Rust支持从类型向Trait对象的向上转型(普通指针到Fat指针)。我无法对其他形式的向上转型做出评论,比如Trait对象之间的转型,因为我还没有详细研究过。 - undefined