没有.没有办法在两个不相关的特征之间施展.要理解原因,我们必须了解如何实现特征对象.首先,让我们来看看TraitObject
.
TraitObject
反映了特质对象的实际实现方式.它们由两个指针组成:data
和vtable
.该data
值只是对原始对象的引用:
#![feature(raw)] trait Foo {} impl Foo for u8 {} use std::{raw, mem}; fn main() { let i = 42u8; let t = &i as &Foo; let to: raw::TraitObject = unsafe { mem::transmute(t) }; println!("{:p}", to.data); println!("{:p}", &i); }
vtable
指向函数指针表.此表包含对每个实现的特征方法的引用,这些方法按一些编译器内部方式排序.
// For this hypothetical input trait Foo { fn one(&self); } impl Foo for u8 { fn one(&self) { println!("u8!") } } // The table is something like this pseudocode const FOO_U8_VTABLE = [impl_of_foo_u8_one];
因此,特征对象知道指向数据的指针以及指向构成该特征的方法列表的指针.根据这些信息,无法获得任何其他数据.
好吧,几乎没办法.正如您可能猜到的,您可以向vtable添加一个返回不同特征对象的方法.在计算机科学中,所有问题都可以通过添加另一层间接(除了太多的间接层)来解决.
但是不能将这
data
部分TraitObject
转化为结构
不安全,没有.特征对象不包含有关原始类型的信息.它只是一个包含内存中地址的原始指针.您可能会将其无法安全地转换为a &Foo
或a &u8
或a &()
,但编译器和运行时数据都不知道它最初的具体类型.
该Any
特征实际上也是通过跟踪原始结构的类型ID来实现的.如果要求引用正确的类型,则特征将为您转换数据指针.
是否有一种模式,而不是我用我的
FooOrBar
特性描述的模式来处理这样的情况,我们需要迭代一堆特征对象,但是它们中的一些稍微不同?
如果您拥有这些特征,那么您可以添加as_foo
到Bar
特征,反之亦然.
您可以创建一个包含a Box
或a Box
和then模式匹配的枚举.
您可以将主体移动bar
到该foo
实现的主体中.
您可以实现第三个特性Quux
,其中呼叫
呼叫Foo::foo
和
呼叫Bar::foo
后跟呼叫Bar::bar
.