如何在 Rust 中定义一个符合 trait 的变量?
How to define a variable that conforms to a trait in 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()
};
目前,编译器会抱怨 arms 中的类型不匹配(File
vs. Stdout
)。我想要的只是将 outputFile
声明为我可以从 Write
特性调用任何方法的东西,没有别的。
Rust 允许我这样做还是我必须将整个 match
表达式作为参数传递给该函数?
如果你想return实现特征的两个(或更多)独立类型之一,那么你需要return一个trait object。
在这种情况下,您需要 return 值来拥有该对象(否则 File
将在 match
结束之前被销毁),所以这是有道理的使用 Box<dyn Write>
。 &Write
和 Box<dyn Write>
等特征对象是“胖”指针,其中包括指向结构的指针(在本例中为 File
或 Stdout
)以及指针到描述如何实现 Write
的 vtable。重要的是,Box<dyn Write>
和 &Write
自动实现 Write
.
这是一个工作版本 (playground):
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()),
}
}
我对你的代码做了一些修改:
添加了 Box<dyn Write>
return 值(如果没有函数,您可能需要 let outputFile: Box<dyn Write> = ...
;如果没有在某处定义类型,编译器将不会能够推断它需要将这两种类型强制转换为共同的 Box<dyn Write>
。一旦编译器知道它需要 Box<dyn Write>
,它就可以 强制转换 a Box<File>
到 Box<dyn Write>
.
将两个结果装箱。
将 fileName
重命名为 file_name
以匹配 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()
};
目前,编译器会抱怨 arms 中的类型不匹配(File
vs. Stdout
)。我想要的只是将 outputFile
声明为我可以从 Write
特性调用任何方法的东西,没有别的。
Rust 允许我这样做还是我必须将整个 match
表达式作为参数传递给该函数?
如果你想return实现特征的两个(或更多)独立类型之一,那么你需要return一个trait object。
在这种情况下,您需要 return 值来拥有该对象(否则 File
将在 match
结束之前被销毁),所以这是有道理的使用 Box<dyn Write>
。 &Write
和 Box<dyn Write>
等特征对象是“胖”指针,其中包括指向结构的指针(在本例中为 File
或 Stdout
)以及指针到描述如何实现 Write
的 vtable。重要的是,Box<dyn Write>
和 &Write
自动实现 Write
.
这是一个工作版本 (playground):
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()),
}
}
我对你的代码做了一些修改:
添加了
Box<dyn Write>
return 值(如果没有函数,您可能需要let outputFile: Box<dyn Write> = ...
;如果没有在某处定义类型,编译器将不会能够推断它需要将这两种类型强制转换为共同的Box<dyn Write>
。一旦编译器知道它需要Box<dyn Write>
,它就可以 强制转换 aBox<File>
到Box<dyn Write>
.将两个结果装箱。
将
fileName
重命名为file_name
以匹配 Rust 约定(并消除警告)。