泛型类型的向下特征
我有以下两个特质:组织、能力。
#![feature(specialization)]
trait Org {}
struct OrgV1 {}
impl Org for OrgV1 {...}
struct OrgV2 {}
impl Org for OrgV2 {...}
trait Capability {}
struct CapV1 {}
impl Capability for CapV1 {...}
struct CapV2 {}
impl Capability for CapV2 {...}
// Capability has a generic associated .ensure method that is able to handle
// any combination of the concrete types of Org and Capability.
// It is implemented with rust's specialization feature: https://rust-lang.github.io/rfcs/1210-impl-specialization.html
trait CapabilityService<O: Org> where Self: Capability {
fn ensure(self, org_config: Arc<O>) -> Result<bool>
}
impl<O: Org, C: Capability> CapabilityService<O> for C {
default fn ensure(self, org_config: Arc<O>) -> Result<bool> {
... // not so important logic
return Ok(true)
}
}
fn main() {
...
// assume I have the following 2 variables I got in runtime by serde's deserealization:
// org_trait: instance Org trait object
// capability_trait: instance Capability trait object
// Given that there is .ensure that can handle any combination of the concrete repo and org
// is there a way in rust to downcast to a generic concrete type, aka:
let concrete_org = org_trait.as_any().downcast_ref::<T: Org>().unwrap()
let concrete_capability = capability_trait.as_any().downcast_ref::<T: Capability>().unwrap()
// where concrete_org and concrete_capability are some concrete types of Org,
// and Capability respectively.
let result = concrete_capability.ensure(concrete_org)
}
我知道我可以做这样的事情:
{
if let Some(org) = org_trait.as_any().downcast_ref::<OrgV1>() {
if Some(cap) = cap_trait.as_any().downcast_ref::<CapV1>() {
cap.ensure(org)
}
...
} else Some(org) = org_trait.as_any().downcast_ref::<OrgV2>() {
...
}
...
}
但是一旦有更多的 Org/Cap 实现,处理起来似乎是一场噩梦(在我的实际情况中,我有 3 个确保工作的特征,我没有包括这些特征)图片有点清楚)
在给定约束的情况下,是否可以将特征向下转换为通用具体类型(因为我们知道无论具体类型是什么,都可以调用 .ensure)?如果可能的话,我想避免编写自己的长嵌套 if let Some
链
I have the following 2 traits: Org, Capability.
#![feature(specialization)]
trait Org {}
struct OrgV1 {}
impl Org for OrgV1 {...}
struct OrgV2 {}
impl Org for OrgV2 {...}
trait Capability {}
struct CapV1 {}
impl Capability for CapV1 {...}
struct CapV2 {}
impl Capability for CapV2 {...}
// Capability has a generic associated .ensure method that is able to handle
// any combination of the concrete types of Org and Capability.
// It is implemented with rust's specialization feature: https://rust-lang.github.io/rfcs/1210-impl-specialization.html
trait CapabilityService<O: Org> where Self: Capability {
fn ensure(self, org_config: Arc<O>) -> Result<bool>
}
impl<O: Org, C: Capability> CapabilityService<O> for C {
default fn ensure(self, org_config: Arc<O>) -> Result<bool> {
... // not so important logic
return Ok(true)
}
}
fn main() {
...
// assume I have the following 2 variables I got in runtime by serde's deserealization:
// org_trait: instance Org trait object
// capability_trait: instance Capability trait object
// Given that there is .ensure that can handle any combination of the concrete repo and org
// is there a way in rust to downcast to a generic concrete type, aka:
let concrete_org = org_trait.as_any().downcast_ref::<T: Org>().unwrap()
let concrete_capability = capability_trait.as_any().downcast_ref::<T: Capability>().unwrap()
// where concrete_org and concrete_capability are some concrete types of Org,
// and Capability respectively.
let result = concrete_capability.ensure(concrete_org)
}
I am aware that I could do something like this:
{
if let Some(org) = org_trait.as_any().downcast_ref::<OrgV1>() {
if Some(cap) = cap_trait.as_any().downcast_ref::<CapV1>() {
cap.ensure(org)
}
...
} else Some(org) = org_trait.as_any().downcast_ref::<OrgV2>() {
...
}
...
}
But it seems like a nightmare to handle once there are more Org/Cap implementations(in my actual case, I have 3 traits that ensure works on, which I didn't include to make the picture a bit clear)
Is it possible to downcast trait to a generic concrete type, given the constraints(since we know that .ensure would be able to be called no matter what the concrete types are)? I would like to avoid writing my own long chain of nested if let Some
s if possible
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
谢谢大家。看来我误解了 Rust 的专业化功能是如何工作的。具体来说,我的思考过程与 RFC 页面上提到的注释相反:
这个默认的 impl 并不意味着对所有 Clone 数据实现 Add,而只是当你执行 impl Add 和 Self: Clone 时,你可以离开关闭添加_分配
Thanks all. It seems like I have misunderstood how rust's specialization feature works. Specifically, my thought process was opposite of the note mentioned on the RFCs page:
This default impl does not mean that Add is implemented for all Clone data, but just that when you do impl Add and Self: Clone, you can leave off add_assign