【问题标题】:How to create a static array of objects that implement a common trait?如何创建实现共同特征的对象的静态数组?
【发布时间】:2021-04-05 03:14:25
【问题描述】:

我正在尝试创建一个实现共同特征的静态对象数组。所有这些结构及其大小在编译时都是已知的。但是当访问结构上定义的字段时,编译器会告诉我该字段不在类型上。

fn main() {
    for &thing in ALL_THINGS {
        println!("{}", thing.name)
    }
}
trait Thing: Sync { }

struct SpecificThing { 
    name: &'static str
}
impl Thing for SpecificThing { }

static ALL_THINGS: &'static [&dyn Thing] = &[&SpecificThing {name: "test"}];

error[E0609]: no field `name` on type `&dyn Thing`
 --> src/main.rs:3:30
  |
3 |         println!("{}", thing.name)
  |                              ^^^^

示例: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=28a29e98cadf97edb8d4ec61703e8959

问题static array of trait objectsCreate vector of objects implementing a trait in RustCan I have a static borrowed reference to a trait object?Vector of objects belonging to a trait 无助于解释为什么会发生这种情况或如何解决它。

请问我在这里做错了什么?有没有更好的方法来解决这个我还没有找到的任务?

【问题讨论】:

    标签: arrays rust static traits


    【解决方案1】:

    定义&dyn Thing 时,会删除有关特定数据类型的所有信息。这意味着您无法访问动态调度对象的字段。

    想象一下,ALL_THINGS 中有两个不同的结构:

    struct SpecificThing { 
        name: &'static str
    }
    struct SpecificAnotherThing { 
        no_name: &'static str
    }
    
    static ALL_THINGS: &'static [&dyn Thing] = &[&SpecificThing {name: "test"}, &SpecificAnotherThing { no_name: "" }];
    

    您无法访问 name 字段,因为 trait Thing 对其实现的具体类型一无所知。因此你不能直接访问它的字段。

    如果你真的需要它,你应该在Thing trait 中定义一个方法,它会返回你需要的值:

    trait Thing: Sync {
       fn name(&self) -> &str;
    }
    // ...
    // ...
    impl Thing for SpecificThing {
       fn name(&self) -> &str {
           self.name
       }
    }
    

    或者您可以使用静态调度和代数数据类型 (enum)。

    【讨论】:

      【解决方案2】:

      您不能从&dyn Thing 访问SpecificThing.name,因为并非所有Things 都有name 字段(忽略特征没有字段的事实)。

      您对dyn Thing 的使用表明您有一组具有一些共同点的对象(结构/枚举)。所有这些共同点必须存在于Thing 中,您才能访问它们。例如,如果名称很常见,您可以添加一个获取名称的函数:

      fn main() {
          for &thing in ALL_THINGS {
              println!("{}", thing.get_name())
          }
      }
      trait Thing: Sync { 
          fn get_name(&self) -> &'static str;
      }
      
      struct SpecificThing { 
          name: &'static str
      }
      impl Thing for SpecificThing {
          fn get_name(&self) -> &'static str {
              self.name
          }
          
      }
      
      static ALL_THINGS: &'static [&dyn Thing] = &[&SpecificThing {name: "test"}];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多