泛型类型的向下特征

发布于 2025-01-15 20:03:01 字数 2179 浏览 6 评论 0原文

我有以下两个特质:组织、能力。

#![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 Somes if possible

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

攒一口袋星星 2025-01-22 20:03:01

谢谢大家。看来我误解了 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文