简体   繁体   English

Rust function 返回通用特征

[英]Rust function to return generic trait

I have two structs implementing same trait.我有两个实现相同特征的结构。 I need a single fuction that returs object of any of these structure.我需要一个函数来返回任何这些结构的 object。

trait特征

pub trait DbfFile{
    fn new(fields: HashMap<String, FieldValue>) -> Self;
}

The structures are结构是

pub struct InsertableAttachable {
    pub f1: String,
    pub f2: String,
    pub f3: String,
    pub f4: i8,
}

impl DbfFile for InsertableAttachable{
    fn new(fields: HashMap<String, FieldValue, RandomState>) -> Self {
        InsertableAttachable {
            // fields
        }
    }
}



// Converting this to generic

impl InsertableAttachable{
    pub fn get_data_vector(mut iter: DatabaseRecordIterator) -> Vec<InsertableAttachable>{
        let mut db_data: Vec<InsertableAttachable> = vec!();
        while let Some(table_row) = iter.next() {
            let fields = table_row.fields;
            db_data.push(InsertableAttachable::new(fields));
        };
        db_data
    }
}

And another structure还有另一种结构

pub struct InsertableAttached {
    pub f1: String,
    pub f2: i32,
    pub f3: i32,
}

impl DbfFile for InsertableAttached {
    fn new(fields: HashMap<String, FieldValue, RandomState>) -> Self {
        InsertableAttached {
           // fields
        }
    }

}

// Converting this to generic

impl InsertableAttached{
    pub fn get_data_vector(mut iter: DatabaseRecordIterator) -> Vec<InsertableAttached>{
        let mut db_data: Vec<InsertableAttached> = vec!();
        while let Some(table_row) = iter.next() {
            let fields = table_row.fields;
            db_data.push(InsertableAttached::new(fields));
        };
        db_data
    }
}

Here are example like this returns box / struct and this one returns an option.这是这样的示例返回框/结构,而 这个返回一个选项。

The following function has compile time error以下function有编译时错误

error[E0277]: the size for values of type `(dyn models::traits::DbfFile + 'static)` cannot be known at compilation time
  --> src/dbf.rs:75:1
   |
75 | / pub fn get_data_vector(&mut iter: DatabaseRecordIterator) -> Vec<DbfFile>{
76 | |     let mut db_data: Vec<DbfFile> = vec!();
77 | |     while let Some(table_row) = iter.next() {
78 | |         let fields = table_row.fields;
...  |
81 | |     db_data
82 | | }
   | |_^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `(dyn models::traits::DbfFile + 'static)`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: required by `std::vec::Vec`

error[E0038]: the trait `models::traits::DbfFile` cannot be made into an object
  --> src/dbf.rs:75:1
   |
75 | pub fn get_data_vector(&mut iter: DatabaseRecordIterator) -> Vec<DbfFile>{
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `models::traits::DbfFile` cannot be made into an object

You would need to box the results in order to be able to return a heterogenous collection via dynamic dispatch:您需要对结果进行装箱,以便能够通过动态调度返回异构集合:

pub fn get_data_vector(&mut iter: DatabaseRecordIterator) -> Vec<Box<dynDbfFile>>

However you will then get the following error:但是,您将收到以下错误:

| pub fn get_data_vector(&mut iter: DatabaseRecordIterator) -> Vec<Box<dyn DbfFile>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `DbfFile` cannot be made into an object
|

The reason for this is that your function returns Self - which is different for each implementation.这样做的原因是您的 function 返回Self - 每个实现都不同。 You would need to change it to a common type to make the trait object-safe (allow dynamic dispatch).您需要将其更改为通用类型以使特征对象安全(允许动态分派)。

An alternative could be to return multiple types via an enumeration:另一种方法是通过枚举返回多种类型:

enum GetDataVectorResult {
    Attachable(InsertableAttachable),
    Attached(InsertableAttached),
}

pub fn get_data_vector(&mut iter: DatabaseRecordIterator) -> Vec<GetDataVectorResult>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM