如何从结构类型 T 转换为结构类型 U,这两者都实现了 Rust 中的特定特征

问题描述 投票:0回答:1

我定义了以下特征:

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 casting traits
1个回答
0
投票

在惯用的 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 游乐场中不可用,因此无法提供游乐场链接

© www.soinside.com 2019 - 2024. All rights reserved.