所以,让我说我有两个小特征, Parser 和触发。 Parser 接受一段字符串,进行一些解析并返回字符串切片而不使用消耗的标记。出错时,会返回错误。 触发器就像 Parser 一样,除了它不期望任何令牌,因此它会做一些事情并可能返回错误。每个触发器都可以视为 Parser ,我想定义使该规则成为现实的函数。这就是我的直觉让我做的事情:
pub trait Parser<'a> {
fn parse(&mut self, &'a [String]) -> Result<&'a [String], Error>;
}
pub trait Trigger {
fn pull(&mut self) -> Option<Error>;
}
impl<'a> Parser<'a> for Trigger {
fn parse(&mut self, tokens: &'a [String]) -> Result<&'a [String], Error> {
match self.pull() {
Some(err) => Err(err),
_ => Ok(tokens) //Returns the tokens untouched
}
}
}
我收到此错误消息:
parsers.rs:37:33: 37:40 error: explicit lifetime bound required
parsers.rs:37 impl<'a> Parser<'a> for Trigger {
^~~~~~~
您能否解释一下发生了什么以及实现我想要的东西的惯用方法。谢谢:))
答案 0 :(得分:6)
Rust中的特征不是常规类型。它们可以用作通用边界或特征对象,是常规类型,但也需要某种间接来处理它们(引用或Box
)。另一方面,您正在尝试为Parser
实施Trigger
。裸露的特征是动态大小的类型,通常它们不能在普通大小类型的任何地方使用。
您真正想要的是为实现Parser
的每种类型实施Trigger
。这可以用非常简单的方式编写:
impl<'a, T> Parser<'a> for T where T: Trigger {
fn parse(&mut self, tokens: &'a [String]) -> Result<&'a [String], Error> {
match self.pull() {
Some(err) => Err(err),
_ => Ok(tokens)
}
}
}
这就是所谓的 blanket impl 模式,它在标准库中广泛使用。但是,它有一些限制,例如,您无法为任何特定Parser
重新实现Trigger
。
BTW,考虑将特征中的'a
生命周期参数移动到其方法中。使用此参数的方式很少有用(当然,这取决于您的实际代码,但仍然如此)。