Rust 在结构中存储特征对象

Rust 在结构中存储特征对象,rust,Rust,这有一堆不同的节点(现在大约有6种节点类型,以后会有更多),我对如何与节点项交互(所有节点都实现了一个节点特征)有点迷茫,所以我需要到处使用框 ListNode看起来像: pub struct ListNode { kind: NodeKind, position: usize, pub nodes: Vec<Box<Node>> } 我会遇到如下借用和大小调整错误,例如: src/parser.rs:186:20: 186:24 error:

这有一堆不同的节点(现在大约有6种节点类型,以后会有更多),我对如何与节点项交互(所有节点都实现了一个
节点
特征)有点迷茫,所以我需要到处使用

ListNode
看起来像:

pub struct ListNode {
    kind: NodeKind,
    position: usize,
    pub nodes: Vec<Box<Node>>
}
我会遇到如下借用和大小调整错误,例如:

src/parser.rs:186:20: 186:24 error: cannot move out of borrowed content [E0507]
src/parser.rs:186         let kind = node.get_kind();
                                     ^~~~
src/parser.rs:186:20: 186:24 error: cannot move a value of type nodes::Node + 'static: the size of nodes::Node + 'static cannot be statically determined [E0161]
src/parser.rs:186         let kind = node.get_kind();
类似于这个测试的东西

我应该如何访问特质对象或这种方法有缺陷的生锈?
是否可以将trait实现为trait(如
Debug
),或者我是否需要为嵌入
节点的每个结构手动实现
Debug

错误来自这样一个事实:
节点上的
get\u kind
方法期望
self
按值,而不是
self
。通过值传递
self
意味着该方法获得对象的所有权(并因此放弃对象和方法的结尾),这在这里是不必要的。通常,默认情况下,您应该使用
&self
,如果您需要更改对象,则应更改为
&mut self
;如果您需要使用对象,则应更改为
self
(例如,因为您需要将对象的一个字段移到其他位置,并且不想克隆它)

顺便说一下,我注意到您为结构实现了。但是,
ToString
的文档说明:

此特性将自动为实现的任何类型实现 特点。因此,不应该实现
ToString
直接:
Display
应该改为实现,您可以得到
ToString
免费实施


<>而不是使用一个特性,你也可以考虑使用<代码> EnUM <代码>,特别是如果节点的类型是预先已知的,并且不需要扩展性的话。另外,如果以后需要确定节点的类型,则使用
enum
(只需进行模式匹配)会更自然

似乎需要所有节点类型都具有
种类
位置
属性。根据您将如何使用这些节点,您可能会发现使用这些字段加上特定类型字段的枚举来定义结构更有用

struct Node {
    //kind: NodeKind, // redundant!
    position: usize,
    specific: SpecificNode,
}

enum SpecificNode {
    List(Vec<Box<Node>>),
    Text(String),
    VariableBlock(Box<Node>),
    Identifier(String),
    Int(i32),
    Float(f32),
    Bool(bool),
}
struct节点{
//种类:NodeKind,//多余!
位置:usize,
具体:具体节点,
}
枚举特定节点{
名单(Vec),
文本(字符串),
可变块(盒),
标识符(字符串),
Int(i32),
浮动(f32),
布尔(布尔),
}
嗯,
SpecificNode
enum看起来很像你的
NodeKind
enum,不是吗?实际上,
kind
字段变得多余,因为您可以通过查看
specific
字段的变量来确定种类

现在,不需要在每种类型的节点上分别实现方法,只需定义一次,尽管每个方法通常需要模式匹配
self
,以便访问任何变量的数据


如果您有只适用于一个特定变量的方法(例如,仅在
列表上有意义的方法),那么使用
enum
方法,您就可以在任何类型的节点上调用它,因为每个
enum
变量都没有不同的类型(从Rust 1.6开始,关于引入此功能的讨论已经展开). 但是,您的代码可能在大多数情况下都在抽象的
节点上工作,并且您必须在调用该方法之前验证您的节点类型,因此您最好将该逻辑直接移动到这些方法中。

节点特性的另一种替代方法是使用枚举变量。这将解决尺寸问题。就像这样:太好了,我没意识到锈枚举有那么强大
struct Node {
    //kind: NodeKind, // redundant!
    position: usize,
    specific: SpecificNode,
}

enum SpecificNode {
    List(Vec<Box<Node>>),
    Text(String),
    VariableBlock(Box<Node>),
    Identifier(String),
    Int(i32),
    Float(f32),
    Bool(bool),
}