【发布时间】:2020-02-10 20:32:42
【问题描述】:
如果我有Box<dyn Trait1 + Trait2>,我可以返回&dyn Trait1 吗?
为了提供一些背景信息,我正在尝试在 rust 中实现一个(专门的)图表。这个SpecialisedGraph 需要一些标准的图算法,我想使用Graph trait 来实现这些,它可以在多个图类型之间共享,但是这段代码没有编译:
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`
编辑:我已编辑问题以反映 cmets
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
}
}
}
【问题讨论】:
-
看来Can I cast between two traits?的答案可能会回答您的问题; Why doesn't Rust support trait object upcasting?。如果没有,请edit您的问题解释差异。否则,我们可以将此问题标记为已回答。
-
另见Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?——返回
&Box<T>是非惯用的。 -
谢谢,我不知道
&Box<T>不是惯用语!不过,我的特征是相互关联的,当我有SpecialisedGraphNode时,我知道它实现了Node
标签: rust