我定义了以下特征:
pub trait TItem {
// some functions
}
我有两个结构体 TArray 和 TObject:
impl TItem for TArray {
// some functions
}
impl TItem for TObject {
// some functions
}
我想实现一个这样的作家:
impl MyWriter {
pub fn write_item(&mut self, item: &TItem) {
if item.is_array() {
write_array(item)
return
}
if item.is_object() {
write_object(item)
return
}
// do something else that's never an error
}
pub fn write_array(&mut self, item: &TArray) { /*code*/ }
pub fn write_object(&mut self, item: &TObject) { /*code*/ }
}
我可以相当容易地在 C、C++ 和 CSharp 中实现这种类型的功能,但对于 Rust 来说相对较新,我还没有找到一种方法来做到这一点,看起来应该很容易,但从我的研究来看,它似乎并不容易是。这怎么办?
在惯用的 Rust 中,标准 OOP 概念(如 C/C++ 或 C# 中的概念)的替代方案是使用
enums
。
您提供的example可以使用
enums
写成:
pub struct TArray {
// some fields ...
}
pub struct TObject {
// some fields ...
}
pub enum TItem {
Array(TArray),
Object(TObject),
}
struct MyWriter;
impl MyWriter {
pub fn write_item(&mut self, item: &TItem) {
match item {
TItem::Array(array) => self.write_array(array),
TItem::Object(object) => self.write_object(object),
}
}
pub fn write_array(&mut self, item: &TArray) {
println!("Called write array")
}
pub fn write_object(&mut self, item: &TObject) {
println!("Called write object")
}
}
fn main() {
let array_item = TItem::Array(TArray {});
MyWriter.write_item(&array_item);
}
这里,
TItem
枚举相当于interface
TItem
,结构体TArray
和TObject
可以被认为是实现classes
的interface
。
现在更加不惯用,并提供 OOP 概念中的示例,有一些板条箱提供向下转换功能以进行 rust,例如
downcast
或 downcast-rs
。
作为示例,使用
downcast-rs
,代码如下:
use downcast_rs::{Downcast, impl_downcast};
trait TItem: Downcast {}
impl_downcast!(TItem);
pub struct TArray {
// some fields ...
}
impl TItem for TArray {}
pub struct TObject {
// some fields ...
}
impl TItem for TObject {}
struct MyWriter;
impl MyWriter {
pub fn write_item(&mut self, item: &dyn TItem) {
if let Some(array) = item.downcast_ref() {
self.write_array(array);
} else if let Some(object) = item.downcast_ref() {
self.write_object(object);
} else {
// handle other cases
}
}
pub fn write_array(&mut self, item: &TArray) {
println!("Called write array")
}
pub fn write_object(&mut self, item: &TObject) {
println!("Called write object")
}
}
fn main() {
let array_item = TArray {};
MyWriter.write_item(&array_item);
}
您可以考虑使用允许您使用
dyncamic_cast
的 C++
等功能的板条箱,或者 is
的
C#
检查
注意:
downcast-rs
在 Rust 游乐场中不可用,因此无法提供游乐场链接