我试图创建一个具有BufWriter
的结构,该结构使用Write
特征,这样该结构可以有一个缓冲的编写器,可以是实现该特征的任何东西:{ {1}},File
等等。但我在我的函数中遇到了一个问题,即创建结构,说我有Stream
。以下是具有相同问题的示例代码。
mismatched types
错误
use std::fs::File;
use std::io::{BufWriter, Write};
pub struct BufWriterStruct<W: Write> {
pub writer: Option<BufWriter<W>>,
}
impl <W: Write>BufWriterStruct<W> {
pub fn new(filename: &str) -> BufWriterStruct<W> {
BufWriterStruct {
writer: Some(BufWriter::new(File::create(filename).unwrap())),
}
}
}
fn main() {
let tmp = BufWriterStruct::new("tmp.txt");
}
如果我将error: mismatched types:
expected `BufWriterStruct<W>`,
found `BufWriterStruct<std::fs::File>`
函数更改为改为使用实现new
特征的参数,并在创建Write
时使用该参数,则可以正常工作。
我觉得前者应该可以做某种方式。
答案 0 :(得分:1)
impl <W: Write>BufWriterStruct<W> {
pub fn new(filename: &str) -> BufWriterStruct<W>
此签名表示以下代码有效:
let tmp : BufWriterStruct<Stdout> = BufWriterStruct::new("tmp.txt");
但是,这显然不适用于new
的实施,因为它会生成BufWriterStruct<File>
,而不是<StdOut>
。如果您想返回BufWriterStruct<File>
,则应相应声明new
函数:
pub fn new(filename: &str) -> BufWriterStruct<File>
但是,仅此更改将使W
块上的impl
参数不受约束,编译器将无法为其推断类型。对此最好的解决方案是将new
方法放在非通用impl
上:
impl BufWriterStruct<File> {
pub fn new(filename: &str) -> BufWriterStruct<File> {
// ...
}
}
请注意,Rust不支持重载(具有相同名称但不同参数列表的方法),因此如果您在同一类型上有两个impl
块(忽略通用参数),每个块都有一个名为new
,当您尝试调用其中一个时,您会收到错误(从Rust 1.4.0开始,仅在单独的impl
块中定义具有相同名称的方法不是编译时错误)。因此,您可能希望使用比new
更明确的名称。
答案 1 :(得分:1)
您的错误在于混合通用和特定:
impl <W: Write>BufWriterStruct<W> {
pub fn new(filename: &str) -> BufWriterStruct<W> {
BufWriterStruct {
writer: Some(BufWriter::new(File::create(filename).unwrap())),
}
}
}
此处,BufWriter
的实例应接受W: Write
,由调用者决定,但该函数实际上会创建File
。
让来电者决定:
impl <W: Write> BufWriterStruct<W> {
pub fn new(writer: W) -> BufWriterStruct<W> {
BufWriterStruct {
writer: Some(BufWriter::new(writer)),
}
}
}
当然,这会稍微改变一下调用:
fn main() {
let tmp = BufWriterStruct::new(File::create("tmp.txt").unwrap());
}
然后it'll work。