作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一些结构同时实现了 Hash
和 MyTrait
.我将它们用作 &MyTrait
特征对象。
现在我要 &MyTrait
也实现 Hash
.我尝试了几件事:
trait MyTrait: Hash {}
:the trait `MyTrait` cannot be made into an object
impl Hash for MyTrait {
fn hash<H: Hasher>(&self, hasher: &mut H) {
// ...
}
}
hash
self
具体类型的方法, 我认为。 MyTrait
上:fn my_hash<H: Hasher>(&self, hasher: &mut H);
MyTrait
上。fn my_hash(&self, hasher: &mut H);
impl<T: 'static + Hash> MyTrait for T {
fn as_any(&self) -> &Any {
self as &Any
}
fn my_hash(&self, hasher: &mut Hasher) {
self.as_any().downcast_ref::<T>().unwrap().hash(hasher)
}
}
the trait bound `std::hash::Hasher: std::marker::Sized` is not satisfied
`std::hash::Hasher` does not have a constant size known at compile-time
Hasher
… Hasher
就是这样,我需要一个通用参数H
可以转换为 Any
Hasher
, 咱们试试吧:trait AnyHasher {
fn as_any(&self) -> &Any;
}
impl<H: 'static + Hasher> AnyHasher for H {
fn as_any(&self) -> &Any {
self as &Any
}
}
impl<T: 'static + Hash, H: 'static + Hasher> MyTrait for T {
// ...
fn my_hash(&self, hasher: &mut AnyHasher) {
let h = hasher.as_any().downcast_ref::<H>().unwrap();
self.as_any().downcast_ref::<T>().unwrap().hash(h)
}
}
the type parameter `H` is not constrained by the impl trait, self type, or predicates
PartialEq
for trait objects ,这很困难,因为需要 trait 对象的具体类型信息。这是通过向下转换解决的,但我没有设法在这里应用该解决方案。
最佳答案
我不是 Rust 专家,但在我看来,您试图将 Rust 变成 Java(不要生气:我真的很喜欢 Java)。
How can I create hashable trait objects?
MyTrait
,
Hash
和
Eq
,并且您想将这些混合结构放入单个哈希表中作为
TunedMyTrait
特征对象。这需要
TunedMyTrait
成为
Hash
的子特征和
Eq
.但是
MyTrait
可以成为特征对象,
TunedMyTrait
不能。
vtable
的方法。我没有详细介绍,但是这个委托(delegate)可能会出现一些问题,并且创建了“安全检查”来避免这些问题。这里:
fn eq(&self, other: &Rhs) -> bool
哪里Rhs = Self
不是对象安全的,因为在运行时,Rhs
被抹去,因此具体类型和大小为other
不知道。 fn hash<H: Hasher>(&self, hasher: &mut H)
不是对象安全的,因为 vtable
并非为每种混凝土类型而构建 H
. MyTrait
是一个特征对象,但
TunedMyTrait
不是。然而只有
TunedMyTrait
对象可能是哈希表的有效键。你能做什么?
PartialEq
(通过类型转换尝试,
How to test for equality between trait objects? ),你现在有另一个来自@Boiethios 的黑客(它基本上使散列成为一个非通用函数)。如果你最终实现了目标,我可以想象代码的 future 读者:“天哪,这家伙想做什么?”或(更糟):“我不确定它的作用,但我很确定如果……它会运行得更快”。你已经破坏了语言的保护,你的代码很可能会产生比你试图解决的问题更糟糕的问题。这让我想起了这样的讨论:
Get generic type of class at runtime .进而?你会用这段代码做什么?
MyTrait
装箱。对象,您使用枚举...可能还有其他方法(如上所述,我不是 Rust 专家)。
I want to compare and hash objects that are runtime-polymorphic.
HashMap
中,这就是问题所在。
(key, value)
.当您
put a pair (key, value)
in an empty bucket ,元组
(key, value)
写入缓冲区数组,位置
pair_start + index * sizeof::<K, V>()
,根据
the definition of offset
.很明显,你需要大小对。
MyTrait
的任何具体类型的每个实例。与
可比 和
可散列值,比方说
id
返回
i64
的方法:
trait MyTrait {
fn id(&self) -> i64; // any comparable and hashable type works instead of i64
}
Foo
和
Bar
具体类型将实现此方法(此处给出的实现完全是愚蠢的):
struct Foo(u32);
impl MyTrait for Foo {
fn id(&self) -> i64 {
-(self.0 as i64)-1 // negative to avoid collisions with Bar
}
}
struct Bar(String);
impl MyTrait for Bar {
fn id(&self) -> i64 {
self.0.len() as i64 // positive to avoid collisions with Foo
}
}
Hash
和
Eq
,为了把
MyTrait
在
HashMap
.但是如果我们为
MyTrait
做这件事,我们得到了一个不能是 trait 对象的 trait,因为
MyTrait
没有大小。让我们为
Box<Trait>
实现它,其大小为:
impl Hash for Box<MyTrait> {
fn hash<H>(&self, state: &mut H) where H: Hasher {
self.id().hash(state)
}
}
impl PartialEq for Box<MyTrait> {
fn eq(&self, other: &Box<MyTrait>) -> bool {
self.id() == other.id()
}
}
impl Eq for Box<MyTrait> {}
id
实现方法
eq
和
hash
.
Box<MyTrait>
: 1.它是大小; 2.它实现了
Hash
和
Eq
.这意味着它可以用作
HashMap
的 key 。 :
fn main() {
let foo = Foo(42);
let bar = Bar("answer".into());
let mut my_map = HashMap::<Box<MyTrait>, i32>::new();
my_map.insert(Box::new(foo), 1);
my_map.insert(Box::new(bar), 2);
println!("{:?}", my_map.get(&(Box::new(Foo(42)) as Box<MyTrait>)));
println!("{:?}", my_map.get(&(Box::new(Foo(41)) as Box<MyTrait>)));
println!("{:?}", my_map.get(&(Box::new(Bar("answer".into())) as Box<MyTrait>)));
println!("{:?}", my_map.get(&(Box::new(Bar("question".into())) as Box<MyTrait>)));
Some(1)
None
Some(2)
None
关于generics - 如何使用通用方法参数创建可散列特征对象/特征对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49711479/
我是一名优秀的程序员,十分优秀!