generics - 作为使用关联类型的特征的结构成员

标签 generics hashmap rust

我对这个问题有一个跟进问题:Expose a HashMap in a generic way that disregards the HashMap value

假设我想使用 HashMapContainer (与上一个问题的第一个答案中定义的相同)作为另一个结构(我们称之为 MyDB )和 MyDB 中的成员constructor 我想决定是否将这个成员构造为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());
}

最佳答案

tl;dr:这是不可能的。

首先,这是无效的:

struct MyDB {
    hash_container: HashMapContainer
}

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

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

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

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

这些方法中的每一种都有不同的权衡。使用类型参数会将类型固定为编译时必须知道的类型。特征对象会更灵活,因为具体类型可以在运行时更改,但具有一些性能影响以及对特征及其使用方式的一些限制。

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

本质上,您的综合要求;动态改变特征实现并依赖于特征的关联类型;不相容。

如果您可以修复关联类型,使其始终相同,那么这就可行:

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

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

此处的实际答案将取决于您的实际需求以及您可以在何处改变它们。

关于generics - 作为使用关联类型的特征的结构成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54233898/

相关文章:

java - 使用 Java Collections/Map 以编程方式执行 SQL 查询

java - 在 HashMap 中一次更新所有值

rust - 在 Rust 中,如何强制一个被阻止读取文件的线程恢复?

graph - 拥有的arena数据结构

java - 当我不知道泛型对象的类型时,如何避免 Java 中未经检查的方法警告?

C# 泛型 & 不会发疯

Java泛型返回类型(具有相似的输入参数)

java - Java中synchronized Hashmap vs ConcurrentHashMap的性能评估

rust - 了解相关的生命周期

Java泛型为什么我不能实例化泛型类型