我想创建一个包含trait的变量。trait的实现在编译时是未知的。因此,我需要一个trait对象。这适用于"普通" trait,但当trait有一个在编译时未知的关联类型时就不行了。
假设AssTrait
是一个trait关联一个类型,AssTraitImpl
是一个struct实现这个trait(见下面的例子),那么AssTraitImpl
示例的trait对象就可以指向vtable,vtable代表AssTraitImpl
实现的方法,或者我错了?
示例
下面的代码不起作用。但是,如果我们从trait中移除关联的类型,它就可以起作用。
trait AssTrait {
type Item;
}
struct AssTraitImpl {
}
impl AssTrait for AssTraitImpl {
type Item = i32;
}
fn main() {
let var: &dyn AssTrait;
}
我收到此错误消息:
error[E0191]: the value of the associated type `Item` (from trait `AssTrait`) must be specified
--> src/main.rs:20:20
|
9 | type Item;
| --------- `Item` defined here
...
20 | let var : &dyn AssTrait;
| ^^^^^^^^ help: specify the associated type: `AssTrait<Item = Type>`
1条答案
按热度按时间3pvhb19x1#
因为类型在运行时之前是未知的,所以关联的类型也是未知的。* 从技术上讲 *,在您的示例中,Rust不需要关心这一点,因为您实际上并没有使用它。但这是一个非常不常见的示例代码。一个关联的类型不用于trait的任何方法参数或返回类型是不常见的。Rust选择不允许未指定的关联类型,而不是检查每个方法是否未使用。也许将来可以改变这一点,因为它将是向后兼容的,但除了一些非常罕见的用例外,我看不到它有多大价值。
正如我所暗示的,如果指定了关联类型,那么它是允许的:
这是因为Rust编译器知道
Item
的类型,但是它强制您使用的所有实现也具有Item = i32
。你也可以通过为关联类型使用trait对象来使它更灵活一些:
现在可以为每个可能关联的类型实现
ItemBehaviour
,并在使用该类型时为其提供所需的任何方法或约束。另一种可能的解决方案是创建另一个没有关联类型的trait,并为实现其他trait的所有类型实现它:
NonAssTrait
的实现可以将任何方法调用委托给AssTrait
示例,前提是它们不公开关联的类型。