Struct members who are traits that use associated types
我对这个问题有一个后续问题:Expose a HashMap in a generic way that disregard the HashMap value
假设我想使用
这是我想要实现的示例代码(它不会编译):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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:这是不可能的。
首先,这是无效的:
1 2 3 | struct MyDB { hash_container: HashMapContainer } |
1 2 3 | struct MyDB<H: HashMapContainer> { hash_container: H, } |
或(2)使用特征对象,例如在
1 2 3 | struct MyDB { hash_container: Box<dyn HashMapContainer>, } |
这些方法中的每一种都有不同的权衡取舍。使用 type 参数会将类型修复为在编译时必须知道的内容。 trait 对象会更加灵活,因为具体类型可以在运行时更改,但具有一些性能影响以及对 trait 及其使用方式的一些限制。
由于您想在运行时根据字符串值选择
基本上,您的综合要求;动态改变 trait 实现并依赖于 trait 的关联类型;不兼容。
如果你可以修复关联的类型,所以它总是一样的,那么这可以工作:
1 2 3 | struct MyDB { hash_container: Box<dyn HashMapContainer<Value = SomeType>>, } |
或者,如果您愿意将特征的实现限制为一组固定的已知类型,那么您可以将它们编码在一个枚举中。
这里的实际答案将取决于您的实际需求以及您可以在哪里弯曲它们。