是否有任何方式转换为通用T,其中T是任意特征类型?

时间:2015-11-19 02:19:50

标签: rust

我的问题标题有点模糊,但实质上我希望实现以下目标:

  • struct Foo实现了BehaviourA和BehaviourB以及BehaviourC
  • struct Bar实现了BehaviourA
  • Foo和Bar都实现了一些内容特征
  • &Content获取对行为的引用(如果已实现)。

从广义上讲,强制Content明确了解BehaviourA等等,可以说明这一点:

fn as_a(&self) -> Option<&BehaviourA>

但是,这要求Content类型明确知道所有行为类型,如果将Content导出为包中的api,则无法实现。

理想情况下,Content会有一个api:

fn behaviour<T>(&self) -> Option<T> where T: Any;

可以在运行时调用:

match content_item.behaviour::<&BehaviourA>() {
  Some(x) => { ... },
  None => {}
}

但是,我找不到任何方法来实现这个功能。

我最好的尝试是这样的:

fn behaviour<T>(&self) -> Option<T> where T: Any {
  let own_type = TypeId::of::<T>();
  if own_type == TypeId::of::<Behaviour>() { return Some(self as T); }
  return None;
}

但结果是:

src/foo.rs:21:62: 21:71 error: non-scalar cast: `&interface::test::Foo` as `T`
src/foo.rs:21       if own_type == TypeId::of::<Behaviour>() { return Some(self as T); }

我很欣赏在运行时没有办法在对象上反省特征列表,但是在这里我明确地在实现中强制转换为已知类型;简单地说,并不总是满足约束T。

有没有办法做到这一点,甚至是不安全的?

显示错误的示例游戏围栏在此处:http://is.gd/fZNFA8

(注意。我见过Can you restrict a generic to T where T is a trait implemented by Self?,但我的问题不同;简而言之,有没有办法,甚至在运行时生成特征引用都不安全?)

1 个答案:

答案 0 :(得分:1)

这里的根本问题是特质不是类型。当你说&BehaviourA时,你没有提到这个特性,你指的是对象安全类型,它是从特征中派生的。您需要做的是告诉Rust T不是类型,而是特征。

可悲的是,从1.6开始,仍然无法做到这一点。

我所知道的唯一方法是制作类似这项工作的东西,明确地, a-la COM:你需要一个基本界面,允许你“强制转换为对{{1}的引用”然后在所有支持的X的每个具体类型上实现它。

如果您愿意使用不安全,凌乱的代码,您可以使用某些宏(playpen)获得模糊的内容:

X