【发布时间】:2018-09-16 10:16:27
【问题描述】:
我正在尝试创建一个 trait,它既可以检索(并返回对)另一个 trait 的 trait 对象的引用,也可以创建一个(并返回它的盒装版本),将选择权留给实现者(其中意味着我需要将返回对象的生命周期限制为生产者的生命周期)。但是,我遇到了错误:
use std::borrow::Borrow;
use std::collections::HashMap;
trait A {
fn foobar(&self) {
println!("!");
}
}
trait ProducerOrContainer {
fn get_a<'a>(&'a self, name: &'a str) -> Option<Box<dyn A + 'a>>;
}
impl<'b, B: Borrow<A>> ProducerOrContainer for HashMap<&'b str, B> {
fn get_a<'a>(&'a self, name: &'a str) -> Option<Box<dyn A + 'a>> {
self.get(name).map(|borrow| Box::new(borrow.borrow()))
}
}
错误是:
error[E0308]: mismatched types
--> src/main.rs:20:9
|
20 | self.get(name).map(|borrow| Box::new(borrow.borrow()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait A, found &A
|
= note: expected type `std::option::Option<std::boxed::Box<dyn A + 'a>>`
found type `std::option::Option<std::boxed::Box<&dyn A>>`
这让我感到困惑,因为我希望 &A 也是 A。我试过impl<'a> A for &'a A,但这也无济于事。有没有办法解决这个问题?
【问题讨论】:
-
A实现一个 trait 并不意味着&A可以。由于 Rust 的 auto-ref 和 auto-deref 行为,有时看起来确实如此。例如,它将自动取消引用一个变量,因此您可以键入foo.bar()而不是(*foo).bar()。 -
为什么还要返回
Box<&dyn A>?装箱参考似乎不是很有用。 -
我注意到
name: &'a str在这里受到了不必要的限制,因为返回的引用没有绑定到name。也许你有ProducerOrContainer的其他实现,其中返回值是从name派生的,但如果没有,摆脱'a会更灵活。
标签: rust trait-objects