如何创建实现公共特质的对象静态数组?

3

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

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 objects、在Rust中创建实现特质的对象向量的问题Create vector of objects implementing a trait in Rust、是否可以拥有指向特质对象的静态借用引用的问题Can I have a static borrowed reference to a trait object?或者将对象向量归属于一种特质的问题Vector of objects belonging to a trait不能解释为什么会发生这种情况,也无法说明如何解决它。

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

2个回答

3
当您定义&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: "" }];

由于特质Thing不知道它所实现的具体类型,因此无法直接访问name字段。因此,您无法直接访问其字段。

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

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

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


1
您无法从 &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"}];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接