You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用枚举替代Any特征对象的装箱实现并保留原有API?

Solution: Implement Downcasting for Your Enum Type

To replace Box<Any> with an enum while keeping the original Container API intact, we need to add a trait that lets the enum safely downcast to specific types. Here's a complete, working implementation:

Step 1: Define a Downcasting Trait

First, create a trait that any enum used with Container must implement. This trait handles the core logic of converting enum variants to strongly-typed references:

use std::any::{Any, TypeId};
use std::collections::HashMap;

// Trait to enable safe downcasting from enum variants to specific types
trait Downcastable {
    fn downcast_ref<T: Any>(&self) -> Option<&T>;
}

Step 2: Update the Container Implementation

Modify the Container to require that G implements our Downcastable trait. This lets the borrow method use the trait's downcasting logic to maintain the original API:

struct Container<G> {
    inner: HashMap<TypeId, G>,
}

impl<G> Default for Container<G> {
    fn default() -> Self {
        Container {
            inner: Default::default(),
        }
    }
}

impl<G: Downcastable> Container<G> {
    pub fn insert<T: Any + Into<G>>(&mut self, data: T) {
        self.inner.insert(TypeId::of::<T>(), data.into());
    }

    pub fn borrow<T: Any>(&self) -> Option<&T> {
        // Look up the enum entry by TypeId, then downcast to the desired type
        self.inner.get(&TypeId::of::<T>())
            .and_then(|enum_val| enum_val.downcast_ref::<T>())
    }
}

Step 3: Implement Traits for Your Custom Enum

Define your enum that wraps all user-defined types, then implement From (to satisfy the Into<G> constraint in insert) and Downcastable:

#[cfg(test)]
mod tests {
    use super::*;

    /// User-defined type implementing Any
    #[derive(Debug, Clone, PartialEq)]
    struct TypeA(u32);

    /// User-defined type implementing Any
    #[derive(Debug, Clone, PartialEq)]
    struct TypeB(String);

    /// Enum replacing Box<Any>
    #[derive(Debug, Clone, PartialEq)]
    enum ContainerEnum {
        TypeA(TypeA),
        TypeB(TypeB),
    }

    // Allow converting user types directly into the enum
    impl From<TypeA> for ContainerEnum {
        fn from(value: TypeA) -> Self {
            ContainerEnum::TypeA(value)
        }
    }

    impl From<TypeB> for ContainerEnum {
        fn from(value: TypeB) -> Self {
            ContainerEnum::TypeB(value)
        }
    }

    // Implement downcasting logic for the enum
    impl Downcastable for ContainerEnum {
        fn downcast_ref<T: Any>(&self) -> Option<&T> {
            match self {
                // Convert each variant to &dyn Any, then downcast to the target type
                ContainerEnum::TypeA(a) => (a as &dyn Any).downcast_ref(),
                ContainerEnum::TypeB(b) => (b as &dyn Any).downcast_ref(),
            }
        }
    }

    // Verify the API works exactly like the original Container
    #[test]
    fn test_container_functionality() {
        let mut container: Container<ContainerEnum> = Container::default();

        // Insert and retrieve TypeA
        let a = TypeA(42);
        container.insert(a.clone());
        assert_eq!(container.borrow::<TypeA>(), Some(&a));

        // Insert and retrieve TypeB
        let b = TypeB("hello rust".to_string());
        container.insert(b.clone());
        assert_eq!(container.borrow::<TypeB>(), Some(&b));

        // Check that non-existent types return None
        assert_eq!(container.borrow::<u32>(), None);
    }
}

Key Notes:

  • The Downcastable trait uses Rust's built-in Any trait to safely validate and convert enum variants. Each variant is cast to &dyn Any first, then downcast_ref returns a strongly typed reference only if the type matches.
  • From implementations let users pass custom types directly to insert without manual enum wrapping, keeping the API clean.
  • The Container interface remains identical to your original implementation—users don't need to change how they interact with it.

内容的提问来源于stack exchange,提问作者E Y

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:02:18