Pri*_*rgo 2 traits downcast rust
如何将特征向下转换为结构,就像这个 C# 示例中那样?
我有一个基本特征和几个派生结构,必须将它们推入单个基本特征向量中。
我必须检查向量的每个项目是否可转换为特定的派生结构,如果是,则将其用作该类型的结构。
这是我的 Rust 代码,我不知道如何实现注释部分。
trait Base {
fn base_method(&self);
}
struct Derived1;
impl Derived1 {
pub fn derived1_method(&self) {
println!("Derived1");
}
}
impl Base for Derived1 {
fn base_method(&self) {
println!("Base Derived1");
}
}
struct Derived2;
impl Derived2 {
pub fn derived2_method(&self) {
println!("Derived2");
}
}
impl Base for Derived2 {
fn base_method(&self) {
println!("Base Derived2");
}
}
fn main() {
let mut bases = Vec::<Box<dyn Base>>::new();
let der1 = Derived1{};
let der2 = Derived2{};
bases.push(Box::new(der1));
bases.push(Box::new(der2));
for b in bases {
b.base_method();
//if (b is Derived1)
// (b as Derived1).derived1_method();
//else if (b is Derived2)
// (b as Derived2).derived2_method();
}
}
Run Code Online (Sandbox Code Playgroud)
从技术上讲,您可以使用as_any
,如本答案中所述:
然而,在循环特征对象向量时进行类型检查和向下转型被认为是代码味道。如果将一堆对象放入一个向量中,然后循环该向量,那么该向量中的对象大概应该扮演类似的角色。
因此,您应该重构代码,以便可以在对象上调用相同的方法,而不管底层的具体类型如何。
从您的代码来看,您似乎纯粹是在检查类型(和向下转型),以便可以调用适当的方法。那么,您真正应该做的是引入另一个特征,该特征提供了一个统一的接口,然后您可以从循环中调用该接口,以便循环根本不需要知道具体类型。
编辑:请允许我添加一个具体的例子来强调这一点,但我将使用 Python 来展示这一点,因为在 Python 中,很容易做你要求做的事情,所以我们可以专注于为什么它不是最佳设计选择:
class Dog:
def bark():
print("Woof woof")
class Cat:
def meow():
print("Meow meow")
list_of_animals = [Dog(), Dog(), Cat(), Dog()]
for animal in list_of_animals:
if isinstance(animal, Dog):
animal.bark()
elif isinstance(animal, Cat):
animal.meow()
Run Code Online (Sandbox Code Playgroud)
这里,Python 的动态类型允许我们将所有对象放入同一个列表中,对其进行迭代,然后在运行时找出类型,以便我们可以调用正确的方法。
但实际上,设计良好的面向对象代码的全部要点是将调用者的负担减轻给对象。这种类型的设计非常不灵活,因为一旦您添加另一种动物,您就必须向您的if
块添加另一个分支,并且您最好在有该分支的任何地方都这样做。
解决方案当然是确定两者所扮演的共同角色,并将该行为抽象到接口中。当然,在Python中我们不需要正式声明这样的接口,所以我们可以在其中添加另一个方法:bark
meow
class Dog:
...
def make_sound():
self.bark()
class Cat:
...
def make_sound():
self.meow()
...
for animal in list_of_animals:
animal.make_sound()
Run Code Online (Sandbox Code Playgroud)
在 Rust 代码中,您实际上有两个选择,这取决于您设计的其余部分。或者,正如我所建议的,添加另一个特征来表达对象所扮演的共同角色(为什么首先将它们放入向量中?)并为所有派生结构实现该特征。或者,将所有各种派生结构表示为同一枚举的不同变体,然后向处理调度的枚举添加一个方法。当然,枚举比使用特征版本更接近外部扩展。这就是为什么解决方案将取决于您的需求。
归档时间: |
|
查看次数: |
5040 次 |
最近记录: |