如果我有一个Box<dyn Trait1 + Trait2>,我可以返回一个&dyn Trait1吗?
为了给出一些背景,我试图在铁锈中实现一个(专门的)图表。这个SpecialisedGraph需要一些标准的图形算法,我希望使用可以跨几个图形类型共享的Graph特性来实现这些算法,但这段代码没有编译:
trait Node {
//...
}
trait Graph {
fn get_node(&self, key: &str) -> Option<&dyn Node>;
}
trait SpecialisedNode {
//...
}
trait SpecialisedGraphNode: SpecialisedNode + Node {}
struct SpecialisedGraph {
nodes: HashMap<String, Box<dyn SpecialisedGraphNode>>
}
impl Graph for SpecialisedGraph {
fn get_node(&self, key: &str) -> Option<&dyn Node> {
match self.nodes.get(key) {
Some(node) => Some(&(**node)),
None => None
}
}
}有错误:
error[E0308]: mismatched types
--> src\main.rs:25:32
|
25 | Some(node) => Some(&(**node)),
| ^^^^^^^^^ expected trait `Node`, found trait `SpecialisedGraphNode`
|
= note: expected reference `&dyn Node`
found reference `&dyn SpecialisedGraphNode`编辑:我编辑了这个问题以反映评论。
EDIT2:使用Shepmaster提供的链接Why doesn't Rust support trait object upcasting?找到了我问题的答案。
下面更新的代码现在开始工作了,谢谢大家。
trait AsNode {
fn as_node(&self) -> &dyn Node;
}
trait Node : AsNode {
//...
}
impl<T: Node> AsNode for T {
fn as_node(&self) -> &dyn Node {
self
}
}
trait Graph {
fn get_node(&self, key: &str) -> Option<&dyn Node>;
}
trait SpecialisedNode : Node {
//...
}
struct SpecialisedGraph {
nodes: HashMap<String, Box<dyn SpecialisedNode>>
}
impl Graph for SpecialisedGraph {
fn get_node(&self, key: &str) -> Option<&dyn Node> {
match self.nodes.get(key) {
Some(node) => Some(node.as_node()),
None => None
}
}
}发布于 2020-02-10 20:39:16
不能,HashMap<String, Box<dyn SpecialisedGraphNode>不是HashMap<String, Box<dyn Node>,所以不能形成那种类型的引用。如果使用不安全的代码执行此操作,则会调用未定义的行为,因为这些框没有相同的数据。
我还认为您的感觉是错误的--至少Java、C++和C# (可以说是最常见的静态类型OO语言)也不允许您这样做。(C#允许您对接口执行IReadOnlyDictionary和协变泛型参数的类似操作。但不适用于混凝土类型。)
您可能需要重新考虑您的Graph特性。它真的必须以散列映射的形式提供对节点的访问吗?也许它可以简单地提供一个函数来查找一个节点,并将其作为一个&dyn Node返回。
https://stackoverflow.com/questions/60157976
复制相似问题