我正在使用具有许多不同节点的解析器(现在大约有6种节点类型,以后再介绍),而如何与节点项进行交互(所有节点都实现了Node
特征)有点迷茫,所以我需要在Box<Node>
任何地方使用。
ListNode
好像:
pub struct ListNode {
kind: NodeKind,
position: usize,
pub nodes: Vec<Box<Node>>
}
但是我无法导出,Clone
因为Node
它没有实现它,并且每当我尝试获取例如这样的测试中的节点类型时:
#[test]
fn test_plain_string() {
let mut parser = Parser::new("plain_string", "Hello world");
parser.parse();
assert_eq!(1, parser.root.nodes.len());
let ref node = parser.root.nodes[0];
let kind = node.get_kind();
assert_eq!(kind, NodeKind::Text);
}
我得到像这样的借用和大小调整错误,例如:
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();
同样的事情也该测试是在测试中。
我应该如何访问特征对象,或者该方法在Rust中存在缺陷?是否可以将特征实现为特征(例如Debug
)或特征?我是否Debug
为嵌入的每个结构手动实现Node
?
这个错误来自一个事实,即get_kind
在方法Node
希望self
通过值,而不是&self
。self
通过值传递意味着该方法获得了对象的所有权(因此删除了该对象并终止了该方法的结尾),在此无需这样做。通常,您应该&self
默认使用,然后更改为&mut self
是否需要使对象突变,或者self
是否需要使用该对象(例如,因为您需要将对象的字段之一移至其他位置,并且您不想克隆它)。
顺便说一句,我注意到您ToString
为您的结构实现了。但是,文档中ToString
指出:
对于实现该
Display
特征的任何类型,该特征都会自动实现。因此,ToString
不应该直接实现:Display
应该实现,您可以ToString
免费获得实现。
除了使用特征以外,您还可以考虑使用enum
,尤其是如果节点的类型事先已知并且不需要扩展性时。另外,如果以后需要确定节点的类型,则使用enum
(执行模式匹配)会更自然。
看来您需要所有节点类型都具有kind
和position
属性。根据您将如何使用这些节点,可能会发现用这些字段以及一个用于特定类型字段的枚举来定义结构更有用。
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),
}
嗯,SpecificNode
枚举看起来很像您的NodeKind
枚举,不是吗?实际上,该kind
字段变得多余,因为您可以通过查看该specific
字段的变体来确定种类。
现在,不必为每种类型的节点分别实现方法,只需定义一次即可,尽管每种方法通常将需要进行模式匹配self
才能访问任何变量的数据。
如果您有仅适用于一个特定变体的方法(例如,仅对有意义List
的enum
方法),则使用该方法,您将能够在任何类型的节点上调用它,因为每种enum
变体没有不同的类型(从Rust 1.6开始;有关引入此功能的讨论)。但是,您的代码可能Node
大多数时候都可以在抽象上运行,并且无论如何都必须在调用该方法之前验证您拥有的节点类型,因此您最好将该逻辑直接移到那些方法中。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句