在尝试Any更好地理解这个特性的同时,我看到它有一个impl阻碍特质本身.我不明白这个结构的目的,或者即使它有一个特定的名称.
我用"普通"特征方法和impl块中定义的方法做了一个小实验:
trait Foo {
fn foo_in_trait(&self) {
println!("in foo")
}
}
impl dyn Foo {
fn foo_in_impl(&self) {
println!("in impl")
}
}
impl Foo for u8 {}
fn main() {
let x = Box::new(42u8) as Box<dyn Foo>;
x.foo_in_trait();
x.foo_in_impl();
let y = &42u8 as &dyn Foo;
y.foo_in_trait();
y.foo_in_impl(); // May cause an error, see below
}
Run Code Online (Sandbox Code Playgroud)
编者注
在Rust的版本中,包括Rust 1.15.0,该行
y.foo_in_impl()会导致错误:Run Code Online (Sandbox Code Playgroud)error: borrowed value does not live long enough --> src/main.rs:20:14 …
我有一个包含多个键和值的源 JSON,我想获取多个目标 JSON 并检查它们是否是该 JSON 的子集:目标 JSON 中的所有字段都存在于源 JSON 中并保持相同的值。
为了实现这一点,我想在 a 的值部分放置几个不同类型的值HashMap并调用equals这些值。
地图中有几种类型的值,我想接受一些键值对并检查是否
这是我想在 Java 中做的一个例子:
boolean isInMap(Map<String, Object> map, String key, Object value) {
return map.containsKey(key) && map.get(key).equals(value);
}
Run Code Online (Sandbox Code Playgroud)
这可能是一个XY 问题,但我如何在 Rust 中做到这一点?
我有一些同时实现Hash和的结构MyTrait。我将它们用作&MyTrait特征对象。
现在我&MyTrait也想实施Hash。我已经尝试了几件事:
天真地trait MyTrait: Hash {}:
the trait `MyTrait` cannot be made into an object
Run Code Online (Sandbox Code Playgroud)然后我尝试了这个:
impl Hash for MyTrait {
fn hash<H: Hasher>(&self, hasher: &mut H) {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
但是我认为我需要委托给hash具体类型的方法self。
因此,天真的下一步是戴上它MyTrait:
fn my_hash<H: Hasher>(&self, hasher: &mut H);
Run Code Online (Sandbox Code Playgroud)
这使我回到了第一点。
我读了一些有关使用特征对象而不是通用参数的内容,这听起来很聪明,因此我将其放在 MyTrait
fn my_hash(&self, hasher: &mut H);
Run Code Online (Sandbox Code Playgroud)
然后,我需要实际执行此操作。最好不要用手为每个特征:
impl<T: 'static + Hash> MyTrait for T {
fn as_any(&self) -> &Any { …Run Code Online (Sandbox Code Playgroud)通常的assert_eq!宏要求在结构中实现 PartialEq - 我有一个特征对象向量 ,Vec<Box<dyn Element>>其中 Element 是需要调试的特征,pub trait Element: std::fmt::Debug。我不能类似地要求,PartialEq因为它需要 Self 作为类型参数,编译器无法将其制作成特征对象。
我见过的解决方案涉及在特征定义中要求一个 eq 关联函数,这对我来说没有吸引力,因为这只是调试代码,而且我认为包含一个无用的方法不会有什么好处并且在构建之外添加特征的 API 可能会造成混淆cargo test。
是否有任何其他(可能不安全)的方法来比较两个特征对象?
我希望能够使用各种不同类型作为 a 中的键HashMap,所有这些都可以实现Hash。这似乎应该是可能的:从阅读文档来看,似乎每个Hasher都会产生一个u64结果,因此它们最终会简化为通用类型。实际上我想做的是:
use std::{collections::HashMap, hash::Hash};
fn x(_: HashMap<Box<dyn Hash>, ()>) {}
Run Code Online (Sandbox Code Playgroud)
我不被允许这样做:
error[E0038]: the trait `std::hash::Hash` cannot be made into an object
--> src/lib.rs:3:9
|
3 | fn x(_: HashMap<Box<dyn Hash>, ()>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::hash::Hash` cannot be made into an object
Run Code Online (Sandbox Code Playgroud)
似乎我可以创建一个Hasher(例如RandomState),用它来手动计算哈希值,然后将u64结果存储在 a 中HashMap<u64, _>,但这似乎过于复杂。我不想再次获取键值,我只需要能够比较哈希值。有HashMap我不知道的替代方案吗?或者我以完全错误的方式看待这个问题?