如何在 Rust 中定义符合特征的变量?

Mat*_*toe 3 traits rust

我想实例化一个变量,我将把它传递给一个带有T: Write. 它将定义如下:

let outputFile = match matches.opt_str("o") {
    Some(fileName) => File::create(fileName).expect("could not open output file"),
    None => std::io::stdout()
};
Run Code Online (Sandbox Code Playgroud)

目前,编译器会抱怨 arm ( Filevs. Stdout) 中的不匹配类型。我想要的只是声明outputFile为我可以从Write特征调用任何方法的东西,没有别的。

Rust 允许我这样做还是我必须将整个match表达式作为参数传递给该函数?

Chr*_*son 7

如果要返回实现 trait 的两个(或多个)独立类型之一,则需要返回一个trait object

在这种情况下,您需要返回值来拥有对象(否则File将在 结束之前销毁match),因此使用Box<dyn Write>. 诸如&Write和 之Box<dyn Write>类的特征对象是“胖”指针,其中包括指向结构(FileStdout在这种情况下)的指针以及指向描述如何实现Write. 重要的是,Box<dyn Write>&Write自动实施Write

这是一个工作版本(操场):

fn get_writer(f: Option<&str>) -> Box<dyn Write> {
    match f {
        Some(file_name) => Box::new(File::create(file_name).expect("could not open output file")),
        None => Box::new(std::io::stdout()),
    }
}
Run Code Online (Sandbox Code Playgroud)

我对您的代码进行了一些更改:

  • 添加了Box<dyn Write>返回值(没有您可能需要的函数let outputFile: Box<dyn Write> = ...;如果没有在某处定义类型,编译器将无法推断它需要将两种类型强制转换为 common Box<dyn Write>。一旦编译器知道它需要Box<dyn Write>,它可以强制aBox<File>Box<dyn Write>.

  • 将两个结果装箱。

  • 重命名fileNamefile_name以匹配 Rust 约定(并使警告静音)。