【问题标题】:Return &dyn Trait1 from Box<dyn Trait1 + Trait2> [duplicate]从 Box<dyn Trait 1 + Trait 2> 返回 dyn Trait [重复]
【发布时间】:2020-02-10 20:32:42
【问题描述】:

如果我有Box&lt;dyn Trait1 + Trait2&gt;,我可以返回&amp;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
        }
    }
}

【问题讨论】:

标签: rust


【解决方案1】:

你不能。 HashMap&lt;String, Box&lt;dyn SpecialisedGraphNode&gt; 不是 HashMap&lt;String, Box&lt;dyn Node&gt;,因此您不能形成对该类型的引用。如果您使用不安全的代码执行此操作,则会调用未定义的行为,因为这些框没有相同的数据。

我也认为你的感觉是错误的——至少 Java、C++ 和 C#(以命名最常见的静态类型 OO 语言)也不允许你这样做。 (C# 允许您对 IReadOnlyDictionary 和一般接口的协变泛型参数执行类似的操作。但不适用于具体类型。)

您可能需要重新考虑您的 Graph 特征。它真的必须以哈希映射的形式访问节点吗?也许它可以简单地提供一个函数来查找一个节点,并将其作为&amp;dyn Node 返回?

【讨论】:

  • 感谢@Sebastian-Redl,这很有帮助。我遇到了另一个问题,所以我只是编辑了我的问题以反映您的 cmets
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 2023-04-01
  • 2023-03-29
  • 1970-01-01
  • 2023-02-26
相关资源
最近更新 更多