【问题标题】:Struct members who are traits that use associated types作为使用关联类型的特征的结构成员
【发布时间】:2019-06-11 12:48:08
【问题描述】:

我对此问题有一个后续问题:Expose a HashMap in a generic way that disregards the HashMap value

假设我想使用HashMapContainer(与上一个问题的第一个答案中定义的相同)作为另一个结构(我们称之为MyDB)和MyDB构造函数中的成员,我想决定是否将此成员构造为HashMapContainerImpl1HashMapContainerImpl2。我不想将MyDB 定义为模板(例如MyDB<T>),因为MyDB 用户不关心HashMap 的值(MyDB 构造函数将决定这一点)。实现它的正确方法是什么?

这是我想要实现的示例代码(它不会编译):

pub trait HashMapContainer {
    type Value;
    fn get_hash_map(&self) -> &HashMap<String, Self::Value>;
    fn get_hash_map_mut(&mut self) -> &mut HashMap<String, Self::Value>;
}

struct MyDB {
    hash_container: HashMapContainer
}

impl MyDB {
    pub fn new(hash_value_type: &str) -> MyDB {
        // have a logic to set hash_container to either 
        // HashMapContainerImpl1 or HashMapContainerImpl2
        // according to hash_value_type
    }

    pub fn count_keys(&self) -> usize {
        self.hash_container.get_hash_map().len()
    }
}

fn main() {
    let db = MyDB::new();
    println!("key count: {}", db.count_keys());
}

【问题讨论】:

标签: generics hashmap rust


【解决方案1】:

tl;dr:这是不可能的。

首先,这是无效的:

struct MyDB {
    hash_container: HashMapContainer
}

HashMapContainer 是一个特征,但您正试图将其用作一种类型。相反,您需要 (1) 引入受 trait 约束的类型参数:

struct MyDB<H: HashMapContainer> {
    hash_container: H,
}

或者 (2) 使用 trait 对象,例如在 Box 中:

struct MyDB {
    hash_container: Box<dyn HashMapContainer>,
}

每种方法都有不同的权衡取舍。使用 type 参数会将类型修复为在编译时必须知道的内容。 trait 对象会更加灵活,因为具体类型可以在运行时发生变化,但会对性能产生一些影响,并对 trait 及其使用方式有一些限制。

由于您想在运行时选择 HashMapContainer 的实现,基于字符串值,您必须使用 trait 对象路由。但是,由于具体类型仅在运行时已知,因此关联类型也仅在运行时已知。这意味着编译器将无法对涉及关联类型的任何内容进行类型检查。

基本上,您的综合要求;动态改变 trait 实现并依赖于 trait 的关联类型;不兼容。

如果你可以修复关联的类型,所以它总是一样的,那么这可以工作:

struct MyDB {
    hash_container: Box<dyn HashMapContainer<Value = SomeType>>,
}

或者,如果您愿意将特征的实现限制为一组固定的已知类型,那么您可以将它们编码在一个枚举中。

此处的实际答案将取决于您的实际需求以及您可以在哪里弯曲它们。

【讨论】:

  • 感谢您的回答!假设我想采用向MyDB 引入类型参数的建议(1),我将如何为MyDB 实现构造函数? (例如MyDB::new()
猜你喜欢
  • 2020-01-03
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
相关资源
最近更新 更多