简体   繁体   English

具有关联类型的特征对象中的 Rust 多态性

[英]Rust polymorphism in trait objects with associated types

I have a trait with a number of implementations that satisfy the common interface:我有许多满足通用接口的实现的特征:

pub trait Schema<'a> {
    // ConfigTypes will be parsed from HTTP POST requests, but different
    // implementations can have different fields and know how to parse
    // themselves
    type ConfigType: rocket::request::FromForm<'a>
    fn configure(&mut self, cfg: Self::Configure);
    // and more...
}

Now imagine I want to implement a simple key/value store to map any number of these schemas from arbitrary strings.现在想象一下,我想从任意字符串中实现一个简单的键/值存储到 map 任意数量的这些模式。 I feel like this should be possible with a HashMap, but what would the type be?我觉得 HashMap 应该可以做到这一点,但是类型是什么?

use std::collections::HashMap;

struct Datastore<'a> {
    cache: HashMap<String, dyn Schema<'b>>
}

This fails complaining that the associated type ConfigType must be specified, but I want to store any implementation of Schema behind this cache!这失败了,抱怨必须指定关联类型ConfigType ,但我想在这个缓存后面存储Schema的任何实现!

I expected the problem is in irregular sizing, since the values of HashMap are expected to have static size.我预计问题出在不规则尺寸上,因为 HashMap 的值预计具有 static 尺寸。 Alright then -- let's add Boxes to things.好吧 - 让我们将 Boxes 添加到事物中。

// as above
struct Datastore<'a> {
    cache: HashMap<String, Box<dyn Schema<'b>>>
}

but alas -- the same error presents.但唉 - 出现同样的错误。 How do I define this structure to be able to hold any Schema implementer?如何定义此结构以容纳任何 Schema 实现者?

The associated type must be known.关联的类型必须是已知的。 Otherwise how does the compiler know what type to use when you call methods that use that type?否则,当您调用使用该类型的方法时,编译器如何知道要使用哪种类型?

There are a few ways around this:有几种方法可以解决这个问题:

  1. You use Box<dyn Schema<ConfigType = &dyn rocket::request::FromForm<'b>, 'b> You might have to implement rocket::request::FromForm<'b> for &dyn rocket::request::FromForm<'b> so it can downcast and pass it to the correct type.您使用Box<dyn Schema<ConfigType = &dyn rocket::request::FromForm<'b>, 'b>您可能必须为&dyn rocket::request::FromForm<'b>实现rocket::request::FromForm<'b> &dyn rocket::request::FromForm<'b>所以它可以向下转换并将其传递给正确的类型。
  2. You just erase the whole type, and use Box<dyn Any> .您只需擦除整个类型,然后使用Box<dyn Any> Now you have to downcast it before you can use it.现在,您必须先对其进行向下转换,然后才能使用它。

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

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