如果我有Box<dyn Trait1 + Trait2>
,我可以返回&dyn Trait1
吗?
为了提供一些背景信息,我正在尝试在rust中实现一个(专用)图。 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
}
}
}
答案 0 :(得分:2)
不能。 HashMap<String, Box<dyn SpecialisedGraphNode>
不是HashMap<String, Box<dyn Node>
,因此您无法形成对该类型的引用。如果使用不安全的代码执行此操作,则会调用未定义的行为,因为这些框没有相同的数据。
我也认为您的感觉是错误的-至少Java,C ++和C#(以最常见的静态类型OO语言命名)也不允许您这样做。 (使用C#,您可以对IReadOnlyDictionary
进行类似的操作,并且通常对接口使用协变泛型参数。但对于具体类型则不行。)
您可能需要重新考虑自己的Graph
特性。是否真的必须以哈希映射的形式授予对节点的访问权限?也许它可以简单地提供一个查询节点并将其返回为&dyn Node
的功能?