是否有一种更惯用的方式来使用像生活时间这样的特征`io :: Read`?

时间:2017-10-20 17:44:19

标签: rust lifetime

我有一个公共特征Parser,它定义了一个外部接口。然后我有一个私有的ParserImpl结构来实现这些方法(实际上,我有几个实现,这是使用特征抽象的背后的想法)。

use std::io;

pub trait Parser {
    // ...omitted
}

struct ParserImpl<R: io::Read> {
    // ...omitted
    stream: R,
}

impl<R: io::Read> ParserImpl<R> {
    // ...methods
    fn new(stream: R) -> ParserImpl<R> {
        ParserImpl {
            // ...omitted
            stream: stream,
        }
    }
}

impl<R: io::Read> Parser for ParserImpl<R> {
    // ...methods
}

要创建解析器实例,我使用函数隐藏ParserImpl

pub fn make_parser<'a, R>(stream: R) -> Box<Parser + 'a>
where
    R: io::Read + 'a,
{
    Box::new(ParserImpl::new(stream))
}

这一切都很好......而且它有效......但make_parser功能使我烦恼。我觉得必须有一种更简单的方法来解决这个问题,因为我错过了一些重要的东西,因为这似乎是一个潜在的陷阱,只要使用像io::Read这样的特征来抽象出数据来源。

我理解需要指定生命周期(Parameter type may not live long enough?),但我有点难过我是否可以同时拥有一个干净简单的界面,并且还使用像io::Read这样的特征。

使用io::Read等我缺少的特征是否有“更清洁”或更为惯用的方法?如果没有,那没关系,但我对Rust很陌生,当我编写上述函数时,我一直在想“这不可能......”

要使此示例可运行,请执行main

fn main() {
    use std::fs;
    let file: fs::File = fs::File::open("blabby.txt").unwrap();
    let parser = make_parser(file);
}

1 个答案:

答案 0 :(得分:0)

编写具有该含义的代码的惯用方式,但您可能不需要这种意义。

例如,如果您不需要来创建盒装特征对象,则可以直接返回参数化值,或者在这种情况下只使用{{1}的结果}。这是我的默认形式,直到我知道我需要一些特质对象提供的动态调度。

您还可能需要ParserImpl::new生命周期,而不是引入新的生命周期'static,但这会减少您可以传递到'a的允许类型的范围:

make_parser