我的问题标题有点模糊,但实质上我希望实现以下目标:
&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?,但我的问题不同;简而言之,有没有办法,甚至在运行时生成特征引用都不安全?)
答案 0 :(得分:1)
这里的根本问题是特质不是类型。当你说&BehaviourA
时,你没有提到这个特性,你指的是对象安全类型,它是从特征中派生的。您需要做的是告诉Rust T
不是类型,而是特征。
可悲的是,从1.6开始,仍然无法做到这一点。
我所知道的唯一方法是制作类似这项工作的东西,明确地, a-la COM:你需要一个基本界面,允许你“强制转换为对{{1}的引用”然后在所有支持的X
的每个具体类型上实现它。
如果您愿意使用不安全,凌乱的代码,您可以使用某些宏(playpen)获得模糊的内容:
X