【发布时间】:2018-04-07 20:03:13
【问题描述】:
我有一些实现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) { // ... } }但我想我需要委托给
self的具体类型的hash方法。 -
所以天真的下一步就是把它放在
MyTrait:fn my_hash<H: Hasher>(&self, hasher: &mut H);这让我回到了第一点。
-
我读过一些关于使用 trait 对象而不是泛型参数的文章,这听起来很聪明,所以我把它放在了
MyTraitfn 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可以转换为AnyHasher,让我们试试: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,这很难,因为需要特征对象的具体类型信息。这是通过向下转换解决的,但我没有设法在此处应用该解决方案。
【问题讨论】:
-
你的第一个例子works for me
-
@Jmb 是的,但不可能制作具有该特征的对象:play.integer32.com/…(或者我不知道如何)
-
我遇到了和这个差不多的情况,你解决了吗?
-
为什么不在第二次尝试调用的 trait 中添加
hash方法? -
@Mark 我正在写 POC